2013-01-07 69 views
0

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

我看着msdn使用async和await关键字,但我不确定需要将哪些方法标记为“async”。在我看来,该服务的自动生成的Reference.cs文件可能需要修改,但我有我的疑惑。更主要的是,我甚至不确定是否需要使用异步和等待,因为我认为它应该像我期望的那样使用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

非常感谢您的帮助! Francis

回答

0

感谢您的建议,Stpehen和托尼。直到我使用了this article中概述的方法时,我仍然一直在努力,虚拟机将回调方法传递给模型,该模型仅使用此方法调用WCF服务。

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

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

3

欢迎来到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; 
} 
+0

当然,真的吗?我想我很惊讶,需要任何“特殊”才能使它与WCF一起工作。该选项在生成服务客户端时被禁用。哦,谢谢你的帮助......我会看看我能想出什么。 –

+0

聚苯乙烯 - 我应该说这个选项被选中,虽然复选框被禁用。 –