Sök…


Pseudocode för nyckelord / vänta på nyckelord

Tänk på en enkel asynkron metod:

async Task Foo()
{
    Bar();
    await Baz();
    Qux();
}

Förenkling kan vi säga att den här koden faktiskt betyder följande:

Task Foo()
{
    Bar();
    Task t = Baz();
    var context = SynchronizationContext.Current;
    t.ContinueWith(task) =>
    {
        if (context == null)
            Qux();
        else
            context.Post((obj) => Qux(), null);
    }, TaskScheduler.Current);

    return t;
}

Det betyder att async som är async / await använder aktuell synkroniseringskontext om de finns. Du kan skriva bibliotekskod som fungerar korrekt i UI-, webb- och konsolapplikationer.

Källartikel .

Inaktiverar synkroniseringskontext

För att inaktivera synkroniseringskontext måste du anropa metoden ConfigureAwait :

async Task() Foo()
{
    await Task.Run(() => Console.WriteLine("Test"));
}

. . .

Foo().ConfigureAwait(false);

ConfigureAwait tillhandahåller ett sätt att undvika standarduppförandet av SynchronizationContext; att passera falskt för parametern flowContext förhindrar att SynchronizationContext används för att återuppta körningen efter väntan.

Citat från It's All About SynchronizationContext .

Varför SynchronizationContext är så viktigt?

Tänk på detta exempel:

private void button1_Click(object sender, EventArgs e)
{
    label1.Text = RunTooLong();
}

Den här metoden fryser UI-applikationen tills RunTooLong är klar. Ansökan kommer inte att svara.

Du kan prova att köra inre kod asynkront:

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(() => label1.Text = RunTooLong());
}

Men den här koden kommer inte att köras eftersom innerkroppen kan köras på tråd utan UI och den bör inte ändra UI-egenskaper direkt :

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(() =>
    {
        var label1Text = RunTooLong();

        if (label1.InvokeRequired)
            lable1.BeginInvoke((Action) delegate() { label1.Text = label1Text; });
        else
            label1.Text = label1Text;
    });
}

Glöm inte alltid att använda detta mönster. Eller prova SynchronizationContext.Post som gör det åt dig:

private void button1_Click(object sender, EventArgs e)
{
    Task.Run(() =>
    {
        var label1Text = RunTooLong();
        SynchronizationContext.Current.Post((obj) =>
        {
            label1.Text = label1    Text);
        }, null);
    });
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow