gpt4 book ai didi

c# - 了解多个 configureawait(false) 在单个异步方法中的作用

转载 作者:行者123 更新时间:2023-11-30 13:43:51 37 4
gpt4 key购买 nike

考虑这段代码:

public async Task SomeMethodAsync(){
//1. code here executes on the original context

//for simplicity sake, this doesn't complete instantly
var result1 = await Method1Async().ConfigureAwait(false);

//2. code here doesn't executes in the original context

现在我的问题是,如果在上面的方法中有另一个异步方法的调用:

    //again for simplicity sake, this doesn't complete instantly 
var result2 = await Method2();
//3. code in question is here
}

有问题的代码是在原始上下文中运行还是在另一个上下文中运行(可能是线程池中的线程或另一个上下文)?

此外,如果使用 ConfigureAwait(false) 调用方法 2,相关代码是否会在与段号 2 相同的上下文中运行?

最佳答案

简化的原始代码

//for simplicity sake, this doesn't complete instantly 
var result1 = await Method1Async().ConfigureAwait(false);

//again for simplicity sake, this doesn't complete instantly
var result2 = await Method2();

//code in question is here

答案

假设您的异步方法不会立即完成,这里有两个简短的答案。

Will the code in question run in the original context or in another context (maybe a thread from the thread pool or another context)?

有问题的代码将有一个空的 SynchronizationContext.Current 值,因此将在默认的 SynchronizationContext 中运行。

关于有问题的代码在哪个线程中运行:SynchronizationContext 做出该决定。代码被发布/发送到 SynchronizationContext,后者又将操作转发到特定的计算资源,例如特定的线程、特定的 CPU 核心或其他。在默认 SynchronizationContext 的情况下,线程的选择取决于托管您的应用程序的对象(例如,控制台应用程序与 ASP.NET 应用程序)。在非默认 SynchronizationContext 的情况下,计算资源的选择取决于实现者的心血来潮:它可以在网络共享上运行。

Also, if method2 would have been called with ConfigureAwait(false) will the code in question run in the same context as segment number 2?

如果方法 2 有 ConfigureAwait(false),那么相关代码也会在默认的 SynchronizationContext 中运行。换句话说,当我们使用 false 时,任务不再尝试在捕获的上下文中继续。

实验

这是一个可以回答您的两个问题的实验 ( the full listing is here)。

实验使用了一个SynchronizationContext,它维护一个简单的string State,在Post期间将自身重置为当前上下文,并覆盖 ToString() 输出其 State 值。

public class MySyncContext : SynchronizationContext
{
public string State { get; set; }

public override void Post(SendOrPostCallback callback, object state)
{
base.Post(s => {
SynchronizationContext.SetSynchronizationContext(this);
callback(s);
}, state);
}

public override string ToString() => State;
}

它的作用是让我们了解代码是否在原始上下文中运行。

那么,让我们记忆一下你问的是什么:

Will the code in question run in the original context or in another context (maybe a thread from the thread pool or another context)?

为了回答这个问题,我们有一个接近您的设置的实验。它首先将原始的 SynchronizationContext 设置为已知状态,然后等待两个异步方法,首先使用 ConfigureAwait(false),记录当前的 SynchronizationContext 一路走来。

static async Task Run()
{
var syncContext = new MySyncContext { State = "The Original Context" };
SynchronizationContext.SetSynchronizationContext(syncContext);

Console.WriteLine("Before:" + SynchronizationContext.Current);

await Task.Delay(1000).ConfigureAwait(false);
Console.WriteLine("After Result1:" + SynchronizationContext.Current);

await Task.Delay(1000);
Console.WriteLine("After Result2:" + SynchronizationContext.Current);
}

您想知道在第二个方法之后运行的代码是否会在原始上下文中运行。输出回答了这个问题。第一个和第二个异步方法都不会将它们的延续发布到原始上下文。

上面带有 ConfigureAwait(false) 的代码输出如下:

Before:The Original Context
After Result1:
After Result2:

如果我们将上面的代码更改为具有ConfigureAwait(true),这两种方法都会在原始上下文中运行它们的延续,并且输出是这样的:

Before:The Original Context        
After Result1:The Original Context
After Result2:The Original Context

就是这样。运行 the full code listing 对我很有启发truefalse 的各种组合,多个不同的 SynchronizationContext 值,以及延迟 0 以查看会发生什么。

What does SynchronizationContext do? 的部分内容也值得一读和 It's All About the SynchronizationContext

关于c# - 了解多个 configureawait(false) 在单个异步方法中的作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49593371/

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