Zoeken…


Pseudocode voor async / wacht op trefwoorden

Overweeg een eenvoudige asynchrone methode:

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

Vereenvoudigend kunnen we zeggen dat deze code eigenlijk het volgende betekent:

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

Het betekent dat async / await sleutelwoorden de huidige synchronisatiecontext gebruiken als deze bestaat. Dat wil zeggen dat u bibliotheekcode kunt schrijven die correct zou werken in UI-, web- en consoletoepassingen.

Bron artikel .

Synchronisatiecontext uitschakelen

Om de synchronisatiecontext uit te schakelen, moet u de methode ConfigureAwait aanroepen:

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

. . .

Foo().ConfigureAwait(false);

ConfigureAwait biedt een manier om het standaardgedrag van SynchronizationContext vastleggen te voorkomen; doorgeven van false voor de parameter flowContext voorkomt dat SynchronizationContext wordt gebruikt om de uitvoering na het wachten te hervatten.

Citaat uit It's All About the SynchronizationContext .

Waarom SynchronizationContext zo belangrijk is?

Beschouw dit voorbeeld:

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

Met deze methode wordt de UI-toepassing bevroren totdat RunTooLong is voltooid. De toepassing reageert niet.

U kunt proberen de binnencode asynchroon uit te voeren:

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

Maar deze code wordt niet uitgevoerd omdat het interne deel kan worden uitgevoerd op een niet-UI-thread en het zou de UI-eigenschappen niet rechtstreeks moeten wijzigen :

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

Vergeet nu niet altijd dit patroon te gebruiken. Of probeer SynchronizationContext.Post die het voor u zal maken:

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow