我在这里有一种非常奇怪的感觉,我错过了一些东西,但现在我已经在这个问题上苦苦挣扎了几个小时,但无法得到它。我有一种任务调度类,它主要接收它启动的正常同步操作,而不是通过 Task.Run() 异步操作。但是,当它收到传递的异步操作时,它会返回而不等待等待任务。我将其简化为以下示例:
private async void Button_OnClick(object sender, RoutedEventArgs e)
{
Logger("Click event received");
await OperationProcessor(async () =>
{
Logger(">>> Starting ACTION, waiting 5 seconds");
await Task.Delay(5000);
Logger(">>> ACTION finished");
});
Logger("Click event finished");
}
private static async Task OperationProcessor(Action operation)
{
Logger("Processing started, waiting a second");
await Task.Delay(1000);
Logger("Launching action");
await Task.Run(operation);
Logger("Returned from action, waiting another second");
await Task.Delay(1000);
Logger("Processing finished");
}
private static void Logger(string message)
{
Console.WriteLine($"{DateTime.Now:dd.MM.yy HH:mm:ss} [{Thread.CurrentThread.ManagedThreadId}] {message}");
}
这会产生以下输出:
1: 16.07.19 10:58:06 [1] Click event received
2: 16.07.19 10:58:06 [1] Processing started, waiting a second
3: 16.07.19 10:58:07 [1] Launching action
4: 16.07.19 10:58:07 [7] >>> Starting ACTION, waiting 5 seconds
5: 16.07.19 10:58:07 [1] Returned from action, waiting another second
6: 16.07.19 10:58:08 [1] Processing finished
7: 16.07.19 10:58:08 [1] Click event finished
8: 16.07.19 10:58:12 [7] >>> ACTION finished
如何让 5 等待 4 开始的操作?
为什么不等待我传递给 Task.Run() 的异步操作?
因为这是不可能的await
a void
.
常见的是talk关于“等待方法”或“等待委托”,但这可能会产生误导。实际发生的情况是,首先调用该方法,然后调用其他方法returns正在等待。并且不可能等待结果Action
因为该代表返回void
.
这是最好的主要原因avoid async void。在这种情况下,async void
很狡猾,因为它是一个 lambda 表达式。
异步相当于void Method()
is async Task MethodAsync()
, 所以异步委托相当于Action is Func<Task>。这就是为什么添加Func<Task>
超载起作用了。您可以同时保留Action
and Func<Task>
重载,编译器会智能地选择Func<Task>
过载async
拉姆达。
我有一种任务调度类
If your Func<Task>
解决方案足够好,然后保持原样。但如果你想更深入一点的话,那就是possible检测(并等待)async void
方法。async void
方法与当前交互SynchronizationContext。既然你有自己的“调度类”,你might想要考虑提供SynchronizationContext
对于该类安排的代码。如果您有兴趣,可以向我借用AsyncContext class它本质上只是一个单线程工作队列SynchronizationContext
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)