2017-07-28 26 views
1

我想一些BackgroundWorkers轉換爲較新的異步/在等待着,我的兩個同事,我不知道如何做到以下幾點:目前我有代碼看起來大致是這樣的:如何將此BackgroundWorker更新爲異步/等待?

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

我倒是要更新的代碼看起來像這樣,但顯然這是行不通的,因爲我需要從一個同步的方法調用它:

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

有沒有辦法做到這一點?我是否以錯誤的方式去做? 主要問題是MyMethod()不應該是異步的,但是我發現的其他任何帖子都只是說將其更改爲異步。即使我可以,這意味着調用它的方法也必須是異步的,並且調用該方法的方法將是異步的,等等。因此,基本上所有東西都變成異步,只是爲了支持這一個方法。我確信有更好的方法。

任何幫助將不勝感激,謝謝!

+0

你走錯了路。你可以做的是使用WaitHandle來阻塞(使用WaitOne),並在工作完成時讓BackgroundWorker設置WaitHandle。 – jdweng

+0

我不希望代碼阻止。目的是在不凍結用戶界面的情況下進行長時間的數據庫加載(5-10秒)。 – AnotherProgrammer

+0

您的原始代碼應該這樣做。看起來你需要後臺工作人員在DoStuff之前完成。所以你需要阻止。 – jdweng

回答

1

一個現有代碼的簡單翻譯將是這樣的:

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

理想情況下,你應該avoid async void。此解決方案的缺點是MyNewMethod現在是「頂級」方法 - 它必須處理所有自己的錯誤和所有問題。但是,由於您的舊BGW代碼具有相同的問題,這至少是朝正確方向邁出的一步。

所以基本上一切都變得異步只是爲了支持這個的一種方法。我相信有更好的方法。

它可以是尷尬到那裏,但異步代碼是容易編寫和測試,如果你使用「async一路」。事情是這樣的:

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

這踢的錯誤處理了鏈,誰就調用MyNewMethodAsync。此外,MyNewMethodAsync現在可以從其他異步方法進行測試和組合。