gpt4 book ai didi

c# - C# 编译器如何知道何时停止异步方法?

转载 作者:太空狗 更新时间:2023-10-29 22:21:20 24 4
gpt4 key购买 nike

我正在尝试了解更多关于 async/await 的信息尤其是编译器如何知道在 async 处“暂停”方法和await无需产生额外的线程。

举个例子,假设我有一个 async方法如

DoSomeStuff();
await sqlConnection.OpenAsync();
DoSomeOtherStuff();

我知道 await sqlConnection.OpenAsync();是我的方法被“暂停”的地方,调用它的线程返回到线程池,一旦 Task跟踪连接打开完成然后找到一个可用线程运行 DoSomeOtherStuff() .

| DoSomeStuff() | "start" opening connection | ------------------------------------ | 
| ---------------------------------------------------------- | DoSomeOtherStuff() - |

这就是我感到困惑的地方。我看OpenAsync的源码( https://referencesource.microsoft.com/#System.Data/System/Data/Common/DBConnection.cs,e9166ee1c5d11996,references ) 它是

    public Task OpenAsync() {
return OpenAsync(CancellationToken.None);
}

public virtual Task OpenAsync(CancellationToken cancellationToken) {
TaskCompletionSource<object> taskCompletionSource = new TaskCompletionSource<object>();

if (cancellationToken.IsCancellationRequested) {
taskCompletionSource.SetCanceled();
}
else {
try {
Open();
taskCompletionSource.SetResult(null);
}
catch (Exception e) {
taskCompletionSource.SetException(e);
}
}

return taskCompletionSource.Task;
}

我想看到编译器知道“切断”线程的某个地方,因为任务已经开始与外部资源通信,但我并没有真正看到,事实上,Open();似乎暗示它正在同步等待。有人能解释一下这是如何变成无线程的“真正异步”代码的吗?

最佳答案

您的方法不一定会在等待时“暂停”。如果您正在等待的任务已经完成(您提供的代码中的情况) - 方法将照常继续。您正在查看的方法实际上不是 SqlConnection 使用的方法,因为 DbConnection 是基类,而方法 OpenAsync 是虚拟的。 SqlConnection 覆盖它并提供真正的异步实现。但是,并非所有提供商都这样做,而那些不这样做的提供商确实会使用您在问题中展示的实现。

当使用这样的实现时——整个过程将同步运行而无需任何线程切换。假设你有

public async Task Do() {
DoSomeStuff();
await sqlConnection.OpenAsync();
DoSomeOtherStuff();
}

并且您使用的提供程序不提供 OpenAsync 的真正异步版本。然后当有人调用 await Do() - 调用线程将执行所有工作(DoSomeStuffOpenAsyncDoSomeOtherStuff ).如果那是 UI 线程——它将在整个持续时间内被阻塞(当人们在 UI 线程中为此类提供者使用“异步”方法时,通常会发生这种情况,假设这会以某种方式将工作从 UI 线程中移开,但这种情况不会发生)。

关于c# - C# 编译器如何知道何时停止异步方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47251581/

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