【发布时间】:2012-07-20 03:52:02
【问题描述】:
我在 WCF 中有一个 Web 服务,它消耗一些外部 Web 服务,所以我想做的是使这个服务异步以释放线程,等待所有外部服务完成,然后返回结果给客户。
使用框架 4.0
public class MyService : IMyService
{
public IAsyncResult BeginDoWork(int count, AsyncCallback callback, object serviceState)
{
var proxyOne = new Gateway.BackendOperation.BackendOperationOneSoapClient();
var proxyTwo = new Gateway.BackendOperationTwo.OperationTwoSoapClient();
var taskOne = Task<int>.Factory.FromAsync(proxyOne.BeginGetNumber, proxyOne.EndGetNumber, 10, serviceState);
var taskTwo = Task<int>.Factory.FromAsync(proxyTwo.BeginGetNumber, proxyTwo.EndGetNumber, 10, serviceState);
var tasks = new Queue<Task<int>>();
tasks.Enqueue(taskOne);
tasks.Enqueue(taskTwo);
return Task.Factory.ContinueWhenAll(tasks.ToArray(), innerTasks =>
{
var tcs = new TaskCompletionSource<int>(serviceState);
int sum = 0;
foreach (var innerTask in innerTasks)
{
if (innerTask.IsFaulted)
{
tcs.SetException(innerTask.Exception);
callback(tcs.Task);
return;
}
if (innerTask.IsCompleted)
{
sum = innerTask.Result;
}
}
tcs.SetResult(sum);
callback(tcs.Task);
});
}
public int EndDoWork(IAsyncResult result)
{
try
{
return ((Task<int>)result).Result;
}
catch (AggregateException ex)
{
throw ex.InnerException;
}
}
}
我的问题是:
-
此代码使用三个线程:一个在 BeginDoWork,另一个在代码进入时被实例化的 匿名方法ContinueWhenAll里面,最后一个when 回调被执行,在本例中为 EndDoWork。这是正确的还是 我在通话中做错了什么?我应该使用任何 同步上下文?注意:同步上下文为空 在主线程上。
-
如果我在两个人之间“共享”信息会发生什么 线程,例如回调函数?这会导致 性能问题或匿名方法就像我的闭包 可以共享数据吗?
使用 Framework 4.5 和 Async and Await
现在有了 Framework 4.5,代码似乎比以前简单多了:
public async Task<int> DoWorkAsync(int count)
{
var proxyOne = new Backend.ServiceOne.ServiceOneClient();
var proxyTwo = new Backend.ServiceTwo.ServiceTwoClient();
var doWorkOne = proxyOne.DoWorkAsync(count);
var doWorkTwo = proxyTwo.DoWorkAsync(count);
var result = await Task.WhenAll(doWorkOne, doWorkTwo);
return doWorkOne.Result + doWorkTwo.Result;
}
但是在这种情况下,当我调试应用程序时,我总是看到代码是在同一个线程上执行的。所以我的问题是:
3.. 当我在等待“可等待”代码时,该线程是否被释放并返回线程池执行更多请求?
3.1。如果是这样,我想当我从等待任务中获得结果时,执行会在之前调用的同一线程上完成。那可能吗?如果该线程正在处理另一个请求会怎样?
3.2 如果不是,如何释放线程以将其发送回具有 Asycn 和 Await 模式的线程池?
谢谢!
【问题讨论】:
-
FWIW,使用异步目标包,您可以将 async/await 用于 4.0 项目。
-
4.0能否返回Task
(即使它不使用async/await)?我想这会稍微简化代码。 Task 实现 IAsyncResult IIRC
标签: wcf asynchronous task-parallel-library async-await