了解单个异步方法中的多个configureawait(false)的作用 [英] Understanding what multiple configureawait(false) do in a single async method

查看:96
本文介绍了了解单个异步方法中的多个configureawait(false)的作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

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 

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

Now for my question, if in the above method there was another call to an async method:

    //again for simplicity sake, this doesn't complete instantly 
    var result2 = await Method2();
    //3. 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)?

此外,如果将使用ConfigureAwait(false)调用method2,那么所讨论的代码是否将在与段号2相同的上下文中运行?

Also, if method2 would have been called with ConfigureAwait(false) will the code in question run in the same context as segment number 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

答案

假设您的异步方法不能立即完成,这是两个简短的答案.

Answers

Assuming that your async methods don't complete instantly, here are two short answers.

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

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中运行.

The code in question will have a null SynchronizationContext.Current value and will thereby run in a default SynchronizationContext.

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

Regarding what thread the code in question runs in: the SynchronizationContext makes that decision. The code gets posted/sent to a SynchronizationContext, which in turn forwards the operation to a specific computational resource, such as a specific thread, specific CPU Core, or something else. In the case of the default SynchronizationContext, the choice of thread depends on what is hosting your application (e.g. console app vs ASP.NET app). In the case of a non-default SynchronizationContext, the choice of computational resource depends on the whim of the implementer: it could run on a network share.

此外,如果将使用ConfigureAwait(false)调用method2,那么所讨论的代码是否将在与段号2相同的上下文中运行?

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

如果method2具有ConfigureAwait(false),则有问题的代码也将在默认的SynchronizationContext中运行.换句话说,当我们使用false时,任务不再试图在捕获的上下文中继续进行.

If method2 had ConfigureAwait(false), then the code in question would also run in a default SynchronizationContext. In other words, when we use false, the Task no longer tries to continue in a captured context.

这是一个实验(完整列表在这里 ),可以回答您的两个问题.

Here is an experiment (the full listing is here) that can answer both of your questions.

实验使用的SynchronizationContext保持简单的string State,在Post期间将自身重置为当前上下文,并覆盖ToString()以输出其State值.

The experiment uses a SynchronizationContext that maintains a simple string State, resets itself as the current context during Post, and overrides ToString() to output its State value.

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;
}

它的作用是让我们看到代码是否在原始上下文中运行.

What that does it let us see whether code is running in the original context or not.

所以,让我们回想一下您的要求是什么

So, lets recall what it is that you asked:

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

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.

To answer that question we have an experiment that is close to your your setup. It first sets the original SynchronizationContext with a known state and then awaits two async methods, using ConfigureAwait(false) on the first, logging the current SynchronizationContext along the way.

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);
}

您想知道在第二种方法之后运行的代码是否将在原始上下文中运行.输出回答了这一点.第一个和第二个异步方法都没有将其延续发布到原始上下文中.

You're wondering whether code that runs after the second method will run in the original context or not. The output answers that. Neither the first nor the second async method post their continuations to the original context.

上面带有ConfigureAwait(false)的代码将输出以下内容:

The code above with ConfigureAwait(false) outputs this:

Before:The Original Context
After Result1:                       
After Result2:               

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

And if we change the above code to have ConfigureAwait(true), both methods run their continuations in the original context, and the output is this:

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

因此,您已经拥有了它.启发我运行完整的代码清单 truefalse的组合,具有多个不同的SynchronizationContext值,并且延迟为0以查看会发生什么.

So there you have it. It was enlightening for me to run the full code listing with various combinations of true and false, with multiple different SynchronizationContext values, and with delays of 0 to see what happens.

还值得阅读 SynchronizationContext做什么的部分内容这全都与SynchronizationContext有关

这篇关于了解单个异步方法中的多个configureawait(false)的作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆