了解ConfigureAwait [英] Understanding ConfigureAwait

查看:163
本文介绍了了解ConfigureAwait的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

试图了解何时应使用ConfigureAwait(). 根据书:

Trying to understand when I should use ConfigureAwait(). According to book:

    When an async method resumes after an await, by default it will resume executing within the same context. This can cause performance problems if that context was a UI context and a large number of async methods are resuming on the UI context.
    Solution
To avoid resuming on a context, await the result of ConfigureAwait and pass false
for its continueOnCapturedContext parameter:

async Task ResumeWithoutContextAsync()
{
 await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

 // This method discards its context when it resumes.
}

什么是上下文以及如何查看ConfigureAwait()更改了示例应用程序中的内容:

What is context and how to see ConfigureAwait() changes things in sample application:

    static async Task ResumeWithoutContextAsync()
    {
        await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(true);
        Console.WriteLine("ManagedThreadId {0}", Thread.CurrentThread.ManagedThreadId);

        // This method discards its context when it resumes.
    }

    static void Main(string[] args)
    {

        ResumeWithoutContextAsync();

        Console.ReadLine();

    }

我当时以为上下文是线程,但不是.

I was thinking that context is Thread, but it is not.

推荐答案

上下文为SynchronizationContext.如果存在并且如果您未使用ConfigureAwait false,则Await将在当前上下文(SynchronizationContext.Current)中发布延续(等待之后的方法的其余部分).如果继续未发布到上下文-它将在线程池线程上执行.在控制台应用程序中,默认情况下没有同步上下文,因此在测试ConfigureAwait中无效.您可以创建虚拟上下文以查看效果:

Context here is SynchronizationContext. Await will post continuation (the rest of the method after await) to current context (SynchronizationContext.Current) if it's present and if you did not use ConfigureAwait false. If continuation is not posted to context - it will be executed on thread pool thread. In console applications there is no synhronization context by default, so in your test ConfigureAwait has no effect. You can create dummy context to see the effect though:

class MySynchornizationContext : SynchronizationContext {
    public override void Post(SendOrPostCallback d, object state) {
        Console.WriteLine("posted");
        base.Post(d, state);
    }

    public override void Send(SendOrPostCallback d, object state) {
        Console.WriteLine("sent");
        base.Send(d, state);
    }
}

然后在Main方法的开头:

SynchronizationContext.SetSynchronizationContext(new MySynchornizationContext());

使用ConfigureAwait(true)(或完全不使用)-您将看到延续已发布到上下文(控制台中的"posted"行).使用ConfigureAwait(false)-您会看到不是.

With ConfigureAwait(true) (or without at all) - you will see that continuation was posted to context ("posted" line in console). With ConfigureAwait(false) - you will see it is not.

实际的同步上下文比当然要复杂得多.例如,UI上下文(例如在Winforms或WPF中)将排队"延续并在一个(UI)线程上执行它们.如您的问题引文中所述,这可能是有问题的,由于各种原因(并可能导致死锁),因此在编写通用库时,使用ConfigureAwait(false以避免这种行为是有益的.

Real synchronization contexts are more complicated than that of course. For example UI context (like in winforms or WPF) will "queue" continuations and execute them on one (UI) thread. That might be problematic as described in your question quote, for various reasons (and may lead to deadlocks), so when you are writing general-purpose library - it's benefical to use ConfigureAwait(false to avoid this behavior.

SynchronizationContext将所有回调都发布到单个线程中,它可以对它们执行任何操作.例如,ASP.NET MVC上下文(至少是旧版本)会将回调发送到请求线程,并且可能有很多请求,所以请求线程很多.

SynchronizationContext is not required to post all callbacks to a single thread of course, it can do anything with them. For example ASP.NET MVC context (old versions at least) will post callbacks to the request thread, and there can be many requests so many request threads.

这篇关于了解ConfigureAwait的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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