如何在基于任务的异步方法中包装如下代码?
void ExecuteThreadedAsync(Action a) {
ThreadPool.QueueUserWorkItem(x=>
{
action();
});
}
目前,此方法称为:
void Method() {
var context = GetSomeContext();
ExecuteThreadedAsync(() =>
{
var result = TimeConsumingWebServiceCall();
context.Result = result;
});
}
但我想要的是:
async void Method() {
var context = GetSomeContext();
await ExecuteTaskBasedAsync(() =>
{
var result = TimeConsumingWebServiceCall();
context.Result = result;
});
}
或者:
async void Method() {
var context = GetSomeContext();
var result = await ExecuteTaskBasedAsync<Result>(() =>
{
var result = TimeConsumingWebServiceCall();
return result;
});
context.Result = result;
}
答案 0 :(得分:3)
这取决于TimeConsumingWebServiceCall()
方法的作用 - 从名称来看,我推断它调用了一个Web服务,time consuming
由于服务响应缓慢而发生。这是一个IO绑定任务。使用ThreadPool.QueueUserWorkItem
或Task.Run
同步调用IO绑定任务通常是一种反模式。您只是将工作卸载到另一个线程,无论如何都会同步阻止Web服务调用。
Task.Run
更适合卸载计算绑定任务。
在您的情况下,您应该调查TimeConsumingWebServiceCall
实际调用Web服务的方式,并且您应该使用异步IO API。
Generate task-based operations
(添加服务引用)。System.Net.WebClient
吗?切换到新的System.Net.Http.HttpClient
- 开始使用其GetStringAsync
或GetStreamAsync
等异步方法。通过这种方式,您可以实际利用异步API的优势,而不必不必阻塞线程。
async Task Method() {
var context = GetSomeContext();
var result = await TimeConsumingWebServiceCallAsync();
context.Result = result;
}
async Task TimeConsumingWebServiceCallAsync() {
var httpClient = new HttpClient();
var results = await httpClient.GetStringAsync(url); // or await wcfProxy.YourWCFMethodAsync();
// do processing if necessary
return results;
}
答案 1 :(得分:0)
您可以使用静态Task.Run
方法:
async void Method() {
var context = GetSomeContext();
await Task.Run(() =>
{
var result = TimeConsumingWebServiceCall();
context.Result = result;
});
}
或
async void Method() {
var context = GetSomeContext();
context.Result = await Task.Run(() => TimeConsumingWebServiceCall());
}
答案 2 :(得分:0)
这是您可以执行的操作,以便包装TimeConsumingWebServiceCall
以便可以异步执行
async void MethodAsync()
{
var context = GetSomeContext();
context.Result = await Task.Factory.StartNew(() =>
{
return TimeConsumingWebServiceCall();
});
}
async void Method()
{
var TimeConsumingTask = Task.Factory.StartNew(() =>
{
return TimeConsumingWebServiceCall();
});
var context = GetSomeContext();
context.Result = await TimeConsumingTask;
}
这背后的原因是甚至在您调用TimeConsumingTask
之前启动GetSomeContext()
,因为它可以与TimeConsumingTask
平行执行。
当GetSomeContext()
完成await
后,TimeConsumingTask
完成分配结果。{/ p>