2017-07-28 2 views
1

Ich versuche, einige BackgroundWorkers auf die neuere async/await, und meine beiden Mitarbeiter zu konvertieren, und ich habe keine Ahnung, wie folgendes zu tun: Zur Zeit habe ich Code, der dies in etwa wie folgt aussieht:Wie aktualisiere ich diesen BackgroundWorker auf async/warte?

// Note the override. This method isn't async and I don't own the base class 
protected override void MyMethod() 
{ 
    backgroundWorker1.RunWorkerAsync(); 
} 

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    DoStuff1(); 
} 

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    DoStuff2(); 
} 

I d‘den Code zu aktualisieren, so aussehen, aber offensichtlich wird dies nicht funktionieren, weil ich es von einer synchronen Methode aufrufen müssen:

// Again note the override. This method isn't async and I don't own the base class 
protected override void MyNewMethod() 
{ 
    // Error: "The 'await' operator can only be used within an async method." 
    await Task.Run((Action)DoStuff1); 
    DoStuff2(); 
} 

gibt es eine Möglichkeit, dies zu erreichen? Gehe ich falsch herum? Das Hauptproblem ist die Tatsache, dass MyMethod() nicht asynchron sein soll, aber alle anderen Posts, die ich gefunden habe, sagen nur, dass sie async ändern sollen. Selbst wenn ich könnte, würde das bedeuten, dass die Methode, die es aufruft, auch asynchron sein müsste, und die Methode, die diese Methode aufruft, wäre asynchron usw. Also wird im Grunde alles asynchron, nur um diese eine Methode zu unterstützen. Ich bin mir sicher, dass es einen besseren Weg gibt.

Jede Hilfe wäre willkommen, danke!

+0

Sie gehen in die falsche Richtung. Was Sie tun können, ist eine WaitHandle zu verwenden, um zu blockieren (WaitOne zu verwenden), und der BackgroundWorker setzt das WaitHandle, wenn die Arbeit abgeschlossen ist. – jdweng

+0

Ich möchte nicht, dass der Code blockiert. Der Zweck besteht darin, eine lange Datenbanklast (5-10 Sekunden) zu laden, ohne die Benutzeroberfläche einzufrieren. – AnotherProgrammer

+0

Ihr Original-Code sollte das tun. Es sieht so aus, als ob der Hintergrundarbeiter vor DoStuff abgeschlossen werden muss. Du musst also blocken. – jdweng

Antwort

1

Eine einfache Übersetzung Ihrer vorhandenen Code würde wie folgt sein:

protected override async void MyNewMethod() 
{ 
    try 
    { 
    await Task.Run(() => DoStuff1()); 
    DoSuccessStuff2(); 
    } 
    catch (Exception ex) 
    { 
    DoErrorStuff2(); 
    } 
} 

Idealerweise sollten Sie avoid async void. Die Nachteile dieser Lösung sind, dass MyNewMethod jetzt eine "Top-Level" -Methode ist - es muss alle seine eigenen Fehler und alles behandeln. Da jedoch Ihr alter BGW-Code das gleiche Problem hatte, ist dies zumindest ein Schritt in die richtige Richtung.

Also im Grunde wird alles async, nur um diese eine Methode zu unterstützen. Ich bin mir sicher, dass es einen besseren Weg gibt.

Es kann umständlich sein, um dorthin zu gelangen, aber asynchronen Code ist viel leichter zu komponieren und zu testen, ob Sie verwenden tun „async den ganzen Weg“. Etwas wie folgt aus:

protected override async Task MyNewMethodAsync() 
{ 
    await Task.Run(() => DoStuff1()); 
    DoSuccessStuff2(); 
} 

Dies tritt Fehler, die Kette zu wer MyNewMethodAsync ruft Handhabung auf. Außerdem ist MyNewMethodAsync nun testbar und aus anderen asynchronen Methoden zusammensetzbar.