C# 将异步调用链接在一起-调用永远不会返回
我有一个异步调用的层次结构。基本上是这样的:C# 将异步调用链接在一起-调用永远不会返回,c#,.net,async-await,C#,.net,Async Await,我有一个异步调用的层次结构。基本上是这样的: async MyObject MainWorker() { return await Task.Run(SomeSynchronousFunction); } async MyObject InbetweenFunction1() { //do some things return await MainWorker(); } async MyObject InbetweenFunction2() { //do so
async MyObject MainWorker()
{
return await Task.Run(SomeSynchronousFunction);
}
async MyObject InbetweenFunction1()
{
//do some things
return await MainWorker();
}
async MyObject InbetweenFunction2()
{
//do some things
return await MainWorker();
}
void ReturnObject TopFunction()
{
Task<MyObject> return1 = InbetweenFunction1();
Task<MyObject> return2 = InbetweenFunction2();
while (!return1.IsComplete || !return2.IsComplete)
Thread.Sleep(100);
//access return1.Return and return2.Return values and return from this function
}
async MyObject MainWorker()
{
返回等待任务。运行(SomeSynchronousFunction);
}
异步MyObject中间函数1()
{
//做一些事情
返回等待MainWorker();
}
异步MyObject中间函数2()
{
//做一些事情
返回等待MainWorker();
}
void ReturnObject TopFunction()
{
任务返回1=中间函数1();
任务返回2=中间函数2();
而(!return1.IsComplete | |!return2.IsComplete)
睡眠(100);
//访问return1.Return和return2.返回值并从此函数返回
}
所以我有几个级别的异步调用。顶级方法进行两次异步调用,等待它们完成(通过轮询),然后访问它们的返回值,并对这些值执行操作。问题是,没有一个异步调用完成。函数SomeSynchronousFunction与Task.Run异步调用,最多需要几秒钟,但我等待了30多秒,没有结果
这是我第一次尝试使用新的async/await关键字。我是否做了一些明显错误的事情?以下是一些可行的代码:
private async Task<string> DoMainWork()
{
await Task.Delay(3000);
return "MainWorker";
}
private async Task<string> InbetweenFunction1()
{
// do something
await Task.Delay(1000);
return await DoMainWork() + "1";
}
private async Task<string> InbetweenFunction2()
{
// do something
await Task.Delay(2000);
return await DoMainWork() + "2";
}
public string TopFunction()
{
string return1 = null;
string return2 = null;
var taskList = new List<Task>();
taskList.Add(Task.Run(async () => return1 = await InbetweenFunction1()));
taskList.Add(Task.Run(async () => return2 = await InbetweenFunction2()));
Task.WaitAll(taskList.ToArray());
return return1 + return2;
}
private async Task DoMainWork()
{
等待任务。延迟(3000);
返回“主要工人”;
}
中间函数1()中的专用异步任务
{
//做点什么
等待任务。延迟(1000);
返回等待域工作()+“1”;
}
中间函数2()中的专用异步任务
{
//做点什么
等待任务。延迟(2000);
返回等待域工作()+“2”;
}
公共字符串TopFunction()
{
字符串return1=null;
字符串return2=null;
var taskList=新列表();
taskList.Add(Task.Run(async()=>return1=wait-InbetweenFunction1());
taskList.Add(Task.Run(async()=>return2=wait-InbetweenFunction2());
Task.WaitAll(taskList.ToArray());
返回1+2;
}
以下是一些可行的代码:
private async Task<string> DoMainWork()
{
await Task.Delay(3000);
return "MainWorker";
}
private async Task<string> InbetweenFunction1()
{
// do something
await Task.Delay(1000);
return await DoMainWork() + "1";
}
private async Task<string> InbetweenFunction2()
{
// do something
await Task.Delay(2000);
return await DoMainWork() + "2";
}
public string TopFunction()
{
string return1 = null;
string return2 = null;
var taskList = new List<Task>();
taskList.Add(Task.Run(async () => return1 = await InbetweenFunction1()));
taskList.Add(Task.Run(async () => return2 = await InbetweenFunction2()));
Task.WaitAll(taskList.ToArray());
return return1 + return2;
}
private async Task DoMainWork()
{
等待任务。延迟(3000);
返回“主要工人”;
}
中间函数1()中的专用异步任务
{
//做点什么
等待任务。延迟(1000);
返回等待域工作()+“1”;
}
中间函数2()中的专用异步任务
{
//做点什么
等待任务。延迟(2000);
返回等待域工作()+“2”;
}
公共字符串TopFunction()
{
字符串return1=null;
字符串return2=null;
var taskList=新列表();
taskList.Add(Task.Run(async()=>return1=wait-InbetweenFunction1());
taskList.Add(Task.Run(async()=>return2=wait-InbetweenFunction2());
Task.WaitAll(taskList.ToArray());
返回1+2;
}
您需要的是一个额外的函数来组合前面的任务
public async Task<string> Combine(Task<string> a, Task<string b){
var aa = await a;
var bb = await b;
return aa + bb;
}
注意,
真正需要使用阻塞调用的地方之一是应用程序的入口点主函数
,它不能声明为异步
,因此不能使用等待
,您需要的是一个额外的函数来组合前面的任务
public async Task<string> Combine(Task<string> a, Task<string b){
var aa = await a;
var bb = await b;
return aa + bb;
}
注意,真正需要使用阻塞调用的地方之一是应用程序的入口点主函数
,它不能声明为异步
,因此不能使用等待
我是不是做错了什么
是的,您正在忙着等待(循环直到条件变为true
),除非没有其他选项,否则您不应该这样做。这里还有一个更好的选择:使用Wait()
,或者Task.WaitAll()
但这样做很可能不会真正使代码正常工作。真正的问题可能是:您处于一个同步上下文中(通常是UI线程或ASP.NET请求上下文),您的wait
s尝试在该上下文上恢复,但您也在阻止该上下文,等待任务完成
解决此问题的正确方法是在TopLevelFunction()
中也使用wait
。这将要求您将该函数也设置为async
,这意味着它的调用者现在也必须是async
,等等。这称为“async
”
所有async
方法都应该是async Task
方法,但顶级事件处理程序除外,它必须是async void
。(但是您不应该在其他任何地方使用async void
方法,因为它们不能wait
ed。)
这意味着您的功能将变为:
async Task<ReturnObject> TopFunction()
{
Task<MyObject> return1 = InbetweenFunction1();
Task<MyObject> return2 = InbetweenFunction2();
await Task.WhenAll(return1, return2);
//access await return1 and await return2 values and return from this function
}
异步任务TopFunction()
{
任务返回1=中间函数1();
任务返回2=中间函数2();
等待任务。WhenAll(返回1,返回2);
//访问Wait return1和Wait return2值并从此函数返回
}
我是不是做错了什么
是的,您正在忙着等待(循环直到条件变为true
),除非没有其他选项,否则您不应该这样做。这里还有一个更好的选择:使用Wait()
,或者Task.WaitAll()
但这样做很可能不会真正使代码正常工作。真正的问题可能是:您处于一个同步上下文中(通常是UI线程或ASP.NET请求上下文),您的wait
s尝试在该上下文上恢复,但您也在阻止该上下文,等待任务完成
解决此问题的正确方法是在TopLevelFunction()
中也使用wait
。这将要求您将该函数也设置为async
,这意味着它的调用者现在也必须是async
,等等。这称为“async
”
A