防止async方法在所有任务完成之前返回
本文关键字:返回 任务 async 方法 防止 | 更新日期: 2023-09-27 18:15:44
所以我仍然试图理解async/await模式,但我也试图实现以下行为:
A方法A调用运行多个进程的方法B。其中一些进程可以在单独的线程上运行,而其他进程正在处理中,这样它们的返回值将在更接近需要时可用。在所有这些进程完成之前,方法B不需要将控制权返回给调用者。
下面是我正在使用的测试代码:
static void Main(string[] args)
{
CallProc();
Console.WriteLine("Program finished");
Console.ReadKey();
}
public static async Task CallProc()
{
var two = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(5000, "two"));
var one = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(500, "one"));
var three = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(1500, "three"));
// some process happens here
var oneMessage = await one; // waits until one finishes and then snags it's value
Console.WriteLine("Got message {0}", oneMessage);
// some more stuff happens here
var twoMessage = await two; // waits until two is finished and then snags it's value
Console.WriteLine(twoMessage);
// TODO: need to make sure that everything is completed before returning control to caller
}
public static string SomeSynchronousProcessIDontOwn(int delayTime, string message, bool delay = true)
{
Console.WriteLine("Starting '"{0}'"", message);
if(delay) Thread.Sleep(delayTime);
return string.Format("Finished '"{0}'"", message);
}
现在,发生的事情是,除了方法在一切完成之前返回之外,所有内容都如我所料,因此输出显示"Program finished",而"two"仍在运行。
我如何写这个,以便CallProc()
可以异步执行这些任务,但延迟返回,直到所有任务都完成。换句话说,CallProc()
需要异步运行一些任务,但CallProc()
本身需要同步调用。
异步方法的思想,也就是你所写的是,它将立即返回控制(大约),并且当它在概念上代表的操作完成时,它返回的任务将被标记为已完成。
这意味着您的程序应该查看结果任务以查看它何时完成,或者您首先不想要异步方法,并且您应该同步而不是异步地重写CallProc
。
要使CallProc
同步,只需删除async
(并相应地调整返回类型),并等待每个任务而不是使用await
。
如果CallProc
真的应该是异步的,那么调用者应该在任务完成时添加一个延续(或使用await
)来执行一个动作,而不是在方法返回时。
与其单独等待每个任务,不如使用WhenAll
等待所有任务
public static async Task CallProc()
{
var two = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(5000, "two"));
var one = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(500, "one"));
var three = Task.Factory.StartNew(() => SomeSynchronousProcessIDontOwn(1500, "three"));
// run synchronous tasks
await Task.WhenAll(one, two, three);
}
如果你更喜欢CallProc
块(即不返回,直到所有的任务完成),然后删除async
声明和使用Task.WaitAll
代替。
public static void CallProc()
{
// start tasks
Task.WaitAll(one, two, three);
}
一种方法是根据CallProc
的结果简单地调用Wait()
。这将在继续之前等待CallProc
返回的任务完成。在GUI应用程序中调用Wait
可能会导致死锁,但对于控制台应用程序来说,这是可以的。
static void Main(string[] args)
{
CallProc().Wait();
Console.WriteLine("Program finished");
Console.ReadKey();
}
这将确保在任务二完成后打印"Program finished"