gpt4 book ai didi

c# - 在非异步方法中使用异步

转载 作者:可可西里 更新时间:2023-11-01 07:56:40 25 4
gpt4 key购买 nike

假设我只想在async 中运行一个方法。

所以我有一个 async 方法,如下所示:

public async Task Load(){
Task task1 = GetAsync(1);
Task task2 = GetAsync(2);
Task task3 = GetAsync(3);
var data1 = await task1; // <--Freezes here when called from GetSomethingElse()
var data2 = await task2;
var data3 = await task3;
..process data..
}

然后我试图在另一个方法中调用那个 async 方法作为一个任务,并希望它等到那段特定的 async 代码是完毕。问题是它不是。当它到达 Load() 中的第一个 await 时,它只是没有完成加载。调试器变为空白并且没有给出其他错误。

是否可以从非 async 方法调用 async 方法,就像这样?我不需要此特定任务是 async 是有原因的,但我需要 Load() 函数。

public void GetSomethingElse(){
var task1 = Load().Wait();
}

这怎么可能?


我什至尝试将 Load() 方法更改为使用 var data = task1.Wait() 等,而不是 await,仍然没有区别,无论我尝试哪种方式。如果有人可以提供帮助,我们将不胜感激。

最佳答案

您的手上可能出现了死锁。您在需要该线程完成的任务上使用 Wait() 阻塞线程,因为在 ASP.Net(也在 GUI 环境中)中使用了 SynchronizationContext

您应该使用 ConfigureAwait(false) 告诉等待者不要捕获该上下文。在第一个 await 上执行此操作就足够了,因为其余的将没有要捕获的 SynchronizationContext:

public async Task Load()
{
Task task1 = GetAsync(1);
Task task2 = GetAsync(2);
Task task3 = GetAsync(3);
var data1 = await task1.ConfigureAwait(false);
var data2 = await task2;
var data3 = await task3;
//..process data.
}

但是,建议始终使用ConfigureAwait,除非您希望捕获SynchronizationContext,因此更好的标准是:

public async Task Load()
{
Task task1 = GetAsync(1);
Task task2 = GetAsync(2);
Task task3 = GetAsync(3);
var data1 = await task1.ConfigureAwait(false);
var data2 = await task2.ConfigureAwait(false);
var data3 = await task3.ConfigureAwait(false);
//..process data.
}

在您的情况下,如果您想在完成所有 任务后继续,您应该使用Task.WhenAll 而不是await 每个任务分别:

public async Task Load()
{
await Task.WhenAll(GetAsync(1), GetAsync(2), GetAsync(3)).ConfigureAwait(false);
// process data.
}

注意:sync over async 通常不被鼓励,因为它没有任何好处(您在整个操作过程中阻塞了一个线程)并且可能导致死锁(就像这个死锁)。

关于c# - 在非异步方法中使用异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27478178/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com