在进行异步WCF调用时,首选哪种方式?
当异步调用WCF服务时,似乎有两种方法可以完成。
1。
WcfClient _client = new WcfClient(); public void One() { _client.BegindoSearch("input", ResultOne, null); } private void ResultOne(IAsyncResult ar) { string data = _client.EnddoSearch(ar); }
2。
public void Two() { WcfClient client = new WcfClient(); client.doSearchCompleted += TwoCompleted; client.doSearchAsync("input"); } void TwoCompleted(object sender, doSearchCompletedEventArgs e) { string data = e.Result; }
使用新的Task
类,我们可以通过在同步中包装同步操作来轻松实现第三种方法。
3。
public void Three() { WcfClient client = new WcfClient(); var task = Task.Factory.StartNew(() => client.doSearch("input")); string data = task.Result; }
它们都使您能够在等待结果时执行其他代码,但我认为Task
更好地控制在检索结果之前或之后执行的操作。
使用一个优于另一个是否有任何优点或缺点? 或者更优选哪种方式?
我不会使用最终版本,因为它将在工作线程而不是I / O线程上运行操作。 如果您在ASP.NET中执行此操作尤其糟糕,在ASP.NET中需要工作线程来处理请求。 更不用说,当你检查它的Result
时,你仍然在主线程上阻塞等待任务完成,所以从技术上讲,你浪费了两个工作线程,或者一个工作者和UI。
WCF客户端的BeginXYZ
和XyzAsync
方法的工作方式基本相同 – 您应根据要支持的用例(分别为APC或事件驱动)选择适当的版本。 例如, BeginXyz
版本(可能违反直觉)在ASP.NET(或MVC)异步页面中更容易使用,而XyzAsync
版本在Windows窗体中更容易使用。
你的第一个例子有问题。 当您调用EndDoSearch时,您当然不应该创建新的WcfClient实例。 您应该将原始实例保留在字段中,或者将其作为状态参数传递。
但总的来说,我更喜欢选项#1,因为它使得使用匿名方法处理结果非常容易。
var client = new WcfClient(); client.BeginDoSearch("input", ar => { var result = client.EndDoSearch(ar); // blah blah }, null);