2013-10-04 13 views
1

運行我創建了一個WCF服務應用程序,基本上什麼都沒有改變,除了名稱,默認的合同是存在的,包含方法GetData(Int32)返回一個字符串。.NET WCF客戶端生成的任務似乎沒有真正在不同的線程

然後我已創建WPF客戶端應用靶向.NET FW 4.5所以其中I添加服務參考所述服務,我可以選擇包括在所產生的服務的客戶端的方法合同基於任務的異步變體。

現在,當我嘗試使用該服務,像這樣:

using (var client = new RhaeoServiceClient()) 
    { 
    client.GetDataAsync(17).ContinueWith(t => MessageBox.Show(t.Result)); 
    MessageBox.Show("inb4"); 
    } 

當從按鈕單擊處理程序,窗口攤位,按鈕保持按下一秒鐘左右,然後"inb4"消息顯示執行,因此,在我看來,任務在主線程上運行並等待網絡,從而凍結UI。

"inb4"點擊後不顯示,似乎在執行任務後,就像我說的,一兩秒鐘等待。之後"inb4"顯示,有結果一個消息框顯示爲好,但有什麼好笑的對我來說是再下一個消息框不等待對我關閉第一個,它只是彈出了第一個後立即開始第一個是秀。

所以這是令人困惑的,因爲它使得它看起來像繼續碼其實是在不同的線程中運行,並且不關心主線程是由第一個消息框阻止。但它如何顯示消息框,它只能從UI線程顯示(對嗎?)?

又爲何第一個消息框,等待執行任務後,則顯示出,然後通過覆蓋下一個沒有被關閉?

回答

0

,直到任務完成的t.Result將阻止調用線程。您可以通過將async/await關鍵字與WCF調用結合使用來實現所需的結果。

private void button1_Click(object sender, EventArgs e) 
    { 
     CallGetDataAsync(17); 
     MessageBox.Show("inb4"); 
    } 

    private async void CallGetDataAsync(int number) 
    { 
     string result = null; 

     var client = new Service1Client(); 
     try 
     { 
      // After this line, control is returned to the calling method; the ConfigureAwait(true) 
      // explicitly indicates that when execution resumes, it should attempt to marshall back 
      // to the calling thread. If you change it to false, you can see that the subsequent 
      // messagebox does not stop you from interacting with your main form. 
      result = await client.GetDataAsync(number).ConfigureAwait(true); 

      // when the async service call completes, execution will resume here 
      client.Close(); 
     } 
     catch 
     { 
      try 
      { 
       client.Close(); 
      } 
      catch 
      { 
       client.Abort(); 
      } 
      throw; 
     } 

     // display the MessageBox, this should block the UI thread 
     MessageBox.Show(result); 
    } 

運行這對同機作爲客戶端上運行的服務,它是很難看到是怎麼回事,因爲WCF服務的調用將返回速度不夠快,你的「inb4」服務的結果,仍然顯示信息。延遲樣本服務方法有助於更好地說明行爲。

public string GetData(int value) 
    { 
     return Task.Delay(TimeSpan.FromSeconds(5)).ContinueWith(_ => string.Format("You entered: {0}", value)).Result; 
    } 

回到最後一個問題,MessageBox可以被後臺線程調用。但是,如果這樣做,它將不會充當模式並阻止您的主要形式。

+0

完美。非常感謝! – user2846145

相關問題