我编写了一个简单的控制台应用程序来测试 ConfigureAwait(false),以解决以同步方式调用异步函数的问题。这就是我模拟事件并尝试以同步方式调用异步函数的方式。
public static class Test2
{
private static EventHandler<int> _somethingEvent;
public static void Run()
{
_somethingEvent += OnSomething;
_somethingEvent(null, 10);
Console.WriteLine("fetch some other resources");
Console.ReadLine();
}
private static void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
FakeAsync().Wait();
}
private static async Task FakeAsync()
{
await Task.Delay(2000).ConfigureAwait(false);
Console.WriteLine($"task completed");
}
}
代码输出如下:
passed value : 10
task completed
fetch some other resources
然后当我将 OnSomething 函数更改为异步void时:
private static async void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
await FakeAsync();
}
输出将更改为:
passed value : 10
fetch some other resources
task completed
您可以看到任务完成部分之前发生了获取一些其他资源,这是我想要的结果。
我的问题是如何通过调用异步函数来实现相同的结果,就像我为 OnSomething 函数编写的第一个签名一样?
在这种情况下,如何使用 ConfigureAwait(false)来帮助我?也许我没有正确使用它。
答案 0 :(得分:3)
我编写了一个简单的控制台应用程序来测试ConfigureAwait(false),以解决以同步方式调用异步函数的问题。
这有两个问题。
ConfigureAwait(false)
不是同步调用异步函数的“问题”的“解决方案”。 one possible hack在某些情况下可以使用,但一般不建议这样做,因为在该函数的整个传递闭包中,您必须使用ConfigureAwait(false)
无处不在-包括第二和第三通话-如果您只错过一个 ,仍然有可能出现死锁。解决从同步函数调用异步函数的问题的最佳解决方案是change the calling function to be asynchronous(一直“异步”)。有时这是不可能的,您需要使用hack,但没有适用于每种情况的技巧。ConfigureAwait(false)
。我的问题是如何通过调用异步函数(如我为OnSomething函数编写的第一个签名)同步来获得相同的结果?
调用代码将阻塞异步代码(例如Wait
),或者不会阻塞(例如await
)。您无法阻止异步代码,并且继续执行。调用线程必须继续执行或阻塞;它不能同时做到。
答案 1 :(得分:1)
这是因为当您调用_somethingEvent(null, 10);
时,没有等待OnSomething
,因此下面的Console.WriteLine("fetch some other resources");
将被允许在执行await FakeAsync();
之后直接运行。
如果您无需等待OnSomething
的完成就可以继续,那就开火忘了:
private static void OnSomething(object sender, int e)
{
Console.WriteLine($"passed value : {e}");
Task.Run(() => FakeAsync());
}