2016-03-11 28 views
0

前言:我是一個愛好者,所以請原諒我的無知;-) 我試圖執行一個基於Web的多功能任務(在線天文板解決方案),它位於與我的主窗口不同的一個類中。我想在後臺執行此操作以保持主窗口處於活動狀態(用於在滾動的LogTextBox中記錄消息)。
在我的主窗口中我稱之爲:在MainWindow Background worker的另一個類中運行HttpClient PostAsync?

public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
     { 
       Astrometry ast = new Astrometry(); 
       ast.OnlineSolve(GlobalVariables.SolveImage); 
     } 

而在天體類停靠在等待httpClient.PostAsync(... 返回到主窗口,並沒有什麼事情發生

class Astrometry 
    { 

public void OnlineSolve(string image) 
     { 
      GetSession(apikey); 
     } 

private async void GetSession(string apikey) 
      { 
      ...misc code 
       using (var httpClient = new HttpClient()) 
        { 
         httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
         HttpContent contentPost = new StringContent(input, Encoding.UTF8, "application/x-www-form-urlencoded"); 

         using (var response = await httpClient.PostAsync(baseAddress, contentPost)) 
         { 
          string responseData = await response.Content.ReadAsStringAsync(); 
           ...more stuff 
       } 
       } 

我想知道這是不是可以這樣做... 在此先感謝!

回答

0

當使用async/await時,您必須確保始終傳播任務。

public async Task OnlineSolve(string image) 
{ 
    await GetSession(apikey).ConfigureAwait(false); 
} 

private async Task GetSession(string apikey) 
{ 
     ...misc code 
    using (var httpClient = new HttpClient()) 
    { 
    httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 
    HttpContent contentPost = new StringContent(input, Encoding.UTF8, "application/x-www-form-urlencoded"); 

    using (var response = await httpClient.PostAsync(baseAddress, contentPost).ConfigureAwait(false)) 
    { 
     string responseData = await response.Content.ReadAsStringAsync().ConfigureAwait(false); 
     ...more stuff 
    } 
    } 
} 
在工人

,並再次:

public async void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    Astrometry ast = new Astrometry(); 

    await ast.OnlineSolve(GlobalVariables.SolveImage); 
} 

主要規則是不破的await鏈。一旦你破壞了它,你就會失去異步操作的蹤跡,並且你失去了操作來等待結果並處理任何錯誤。

另請注意,由於您使用的是純異步I/O,因此您並不需要首先使用後臺工作程序。只需從你的按鈕點擊處理程序或任何其他方式直接運行異步方法,你會沒事的。如果你還需要做一些CPU的工作,Task.Run是一個體面的選擇。我甚至不確定後臺工作人員是否將await編組回正確的線程(編輯:而事實上,它並沒有;因此,使用BackgroundWorkerawait確實沒有任何意義,這只是令人困惑 - 僅對CPU工作使用Task.Run,對異步I/O使用await)。

需要記住的是,await基本上起着魔術般的作用return(類似於,如果您曾經使用過)。只要執行到達等待未完成任務的await,則方法return即爲Task(如果可能)。這就是調用者獲得流量控制的地方 - 如果您在調用者中不使用await,那麼當調用者繼續執行時,這是工作所處的狀態。有時候,這是可取的 - 例如,在並行啓動多個任務時。通常情況下,您只需立即想要await所有異步方法。

+0

謝謝!工作得很好,我接受了您的建議並淘汰了後臺工作人員。 – ksipp01

+0

@Luaan:僅供參考,後臺工作人員將在第一次產生「await」時退出。 DoWork在線程池線程上恢復。我發現這種行爲混淆了(即,「完成」被激發爲「早期」),所以如果你需要的話,我推薦BGW上的Task.Run。這當然不在這種情況下。 –

+0

@StephenCleary是的,我有點期待這樣的事情會發生。如果它使用了自己的同步上下文,那麼它能夠工作的唯一方法就是如果沒有等待,這將是毫無意義的。我會將其添加到答案中。 – Luaan

相關問題