【问题标题】:How to properly wait for WCF asynchrony如何正确等待 WCF 异步
【发布时间】:2013-01-11 00:06:42
【问题描述】:

这是我在板上的第一个问题。我正在使用 WCF 和 MVVM 模式编写我的第一个企业级 Silverlight (5) 应用程序。我的问题是我不明白如何让模型类调用 WCF 服务,并且(问题出在这里)等待等待结果,然后再将它们返回到调用视图模型。

我查看了 msdn 以了解 async 和 await 关键字的用法,但我不确定需要将哪种方法标记为“async”。在我看来,服务的自动生成的 Reference.cs 文件可能需要修改,但我有疑问。更重要的是,我什至不确定我是否需要使用 async 和 await,因为我认为通过使用 WCF 应该可以正常工作。

无论如何,这是我拥有的模型类。我希望在 WCF 调用完成后执行 return 语句,但事实并非如此:

public class CRMModel
{
    ObservableCollection<CarrierInfo> carrierInfoCollection = new ObservableCollection<CarrierInfo>();

    public ObservableCollection<CarrierInfo> GetCarrierInformation()
    {
        var client = new CarrierRateService.CarrierRateServiceClient();
        client.GetCarrierInformationCompleted += (s, e) =>
        {
            var info = e.Result;
            carrierInfoCollection = info;
            System.Diagnostics.Debug.WriteLine("Just got the result set: " + carrierInfoCollection.Count);

        };

        client.GetCarrierInformationAsync();

        System.Diagnostics.Debug.WriteLine("About to return with: " + carrierInfoCollection.Count);
        return carrierInfoCollection;
    }
}

你可能猜到了,结果是:

即将返回:0

刚得到结果集:3

非常感谢您的帮助! 弗朗西斯

【问题讨论】:

    标签: wcf mvvm asynchronous wait async-await


    【解决方案1】:

    欢迎来到 SO!

    首先,要在 Silverlight 5 中启用asyncawait,您需要安装Microsoft.Bcl.Async package(目前处于测试阶段)。

    接下来,您需要解决 WCF 代理生成器没有生成 await 兼容的异步方法这一事实。解决此问题的最简单方法是选中 Visual Studio 2012 添加服务引用对话框中的相应框。不过,我不能 100% 确定这是否适用于 Silverlight,所以如果没有,您可以 use TaskCompletionSource to create your own async-compatible wrapper

    这是完整的示例代码:

    public static Task<ObservableCollection<CarrierInfo>> GetCarrierInformationTaskAsync(this CarrierRateService.CarrierRateServiceClient @this)
    {
        var tcs = new TaskCompletionSource<ObservableCollection<CarrierInfo>>();
    
        @this.GetCarrierInformationCompleted += (s,e) =>
        {
            if (e.Error != null) tcs.TrySetException(e.Error);
            else if (e.Cancelled) tcs.TrySetCanceled();
            else tcs.TrySetResult(e.Result);
        };
        @this.GetCarrierInformationAsync(url);
        return tcs.Task;
    }
    

    您现在可以使用以下代码等待它:

    public ObservableCollection<CarrierInfo> GetCarrierInformation()
    {
        var client = new CarrierRateService.CarrierRateServiceClient();
        carrierInfoCollection = await client.GetCarrierInformationTaskAsync();
        System.Diagnostics.Debug.WriteLine("Just got the result set: " + carrierInfoCollection.Count);
    
        System.Diagnostics.Debug.WriteLine("About to return with: " + carrierInfoCollection.Count);
        return carrierInfoCollection;
    }
    

    【讨论】:

    • 当,真的吗?我想我很惊讶需要任何“特殊”才能使其与 WCF 一起使用。生成服务客户端时禁用该选项。哦,好吧,谢谢你的帮助...我会看看我能想出什么。
    • PS - 我应该说该选项已被选中,尽管该复选框已禁用。
    【解决方案2】:

    感谢您的建议,Stpehen 和 Toni。在我使用this article 中概述的方法之前,我仍在苦苦挣扎,VM 将回调方法传递给模型,模型仅使用此方法调用 WCF 服务。

    当我最初在模型中的匿名函数中指定逻辑时,我遇到了异步的计时问题。

    我来自大型机背景,所以 .NET 中这种简单的东西对我来说仍然很新奇。 :)

    【讨论】:

      猜你喜欢
      • 2019-03-03
      • 2018-02-13
      • 2020-09-10
      • 2018-07-27
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      • 1970-01-01
      相关资源
      最近更新 更多