await ohne ConfigureAwait (false) wird in einem anderen Thread fortgesetzt

8

Ich habe eine WinForms-App und ich benötige Code, der auf dem UI-Thread ausgeführt werden muss. Der Code nach dem await wird jedoch auf einem anderen Thread ausgeführt.

%Vor%

Ich habe auch versucht, ConfigureAwait(true) explizit hinzuzufügen, aber das macht keinen Unterschied. Mein Verständnis war, dass, wenn ich ConfigureAwait(false) weglasse, sollte die Fortsetzung auf dem ursprünglichen Thread laufen. Ist das in einigen Situationen falsch?

Ich habe auch bemerkt, dass, wenn ich der Sammlung vor der Wartezeit ein Steuerelement hinzufüge, die Fortsetzung magisch auf dem richtigen Thread läuft.

%Vor%

Meine Frage ist:

  1. Warum passiert das?
  2. Wie überzeuge ich die Fortsetzung davon, auf dem UI-Thread zu laufen (idealerweise ohne meinen Hack, ein Steuerelement hinzuzufügen und zu entfernen)?

Als Referenz sind hier die wichtigen Teile von DoSomethingAsync . Es sendet eine HTTP-Anfrage mit RestSharp.

%Vor%     
AJ Richardson 25.08.2015, 18:37
quelle

2 Antworten

1

Es scheint, dass mit OnHandleCreated etwas Seltsames passiert. Meine Lösung war, stattdessen OnLoad zu verwenden. Ich bin ziemlich glücklich mit dieser Lösung, weil es wirklich keinen Grund gibt, OnHandleCreated in meiner Situation zu verwenden.

Ich bin immer noch neugierig, warum das passiert, also wenn jemand weiß, fühlen Sie sich frei, eine andere Antwort zu posten.

Bearbeiten:

Ich habe das echte Problem gefunden: Es stellte sich heraus, dass ich Form.ShowDialog() nach einem ConfigureAwait(false) aufgerufen habe. Daher wurde das Formular im UI-Thread erstellt, aber ich habe ShowDialog in einem Thread ohne Benutzeroberfläche aufgerufen. Ich bin überrascht, dass das überhaupt funktioniert hat.

Ich habe ConfigureAwait(false) entfernt, sodass jetzt ShowDialog im UI-Thread aufgerufen wird.

    
AJ Richardson 25.08.2015, 20:12
quelle
7
  

Mein Verständnis war, dass wenn ich ConfigureAwait (false) weglasse, sollte die Fortsetzung auf dem ursprünglichen Thread laufen. Ist das in einigen Situationen falsch?

Was tatsächlich passiert, ist, dass await standardmäßig den aktuellen Kontext erfasst und diesen Kontext verwendet, um die Methode async wieder aufzunehmen. Dieser Kontext ist SynchronizationContext.Current , außer es ist null , in diesem Fall ist es TaskScheduler.Current (normalerweise der Thread-Pool-Kontext). Die meiste Zeit hat der UI-Thread eine UI SynchronizationContext - im Fall von WinForms eine Instanz von WinFormsSynchronizationContext .

  

Ich habe auch bemerkt, dass, wenn ich der Sammlung vor der Wartezeit ein Steuerelement hinzufüge, die Fortsetzung magisch auf dem richtigen Thread läuft.

Kein Thread beginnt automatisch mit einem SynchronizationContext . Die WinForms SynchronizationContext wird auf Anforderung installiert, wenn das erste Steuerelement erstellt wird. Aus diesem Grund sehen Sie nach dem Erstellen eines Steuerelements die Fortsetzung in einem Benutzeroberflächenthread.

Da der Wechsel zu OnLoad eine praktikable Lösung ist, empfehle ich Ihnen, einfach mitzugehen. Die einzige andere Option (die Fortsetzung auf dem UI-Thread vor dem Erstellen eines Steuerelements) besteht darin, ein Steuerelement vor dem ersten await manuell zu erstellen.

    
Stephen Cleary 25.08.2015 20:40
quelle

Tags und Links