2017-07-27 59 views
0

我做了這樣的功能:如何使一個方法異步當我需要等待一個事件

public void GetData(string dataToPost) 
{ 
    var url = "some URL"; 

    using (var client = new WebClient()) 
    { 
     client.Headers[HttpRequestHeader.ContentType] = "application/json"; 

     client.UploadStringCompleted += (s, e) => 
      { 
       Console.WriteLine("Result is here"); 
       Console.WriteLine(e.Result); 
      }; 

     client.UploadStringAsync(new System.Uri(url), "POST", dataToPost); 
    } 
} 

這裏的問題是,我想(從服務器返回的值HTTP事實響應)。

我希望我的函數是異步的,所以例如我希望能夠在循環中調用它5次,而不必等待每次調用在下一次調用之前返回一些內容。

我不知道如何實現它。我試圖創建一些任務對象來等待它,但任務需要一個委託,我不知道我可以給它什麼代表。

上面的te函數使用了一個事件,當結果出現時觸發 - 所以我需要返回該結果。

我該怎麼做?

+0

這是一個控制檯應用程序。我對這一切都很陌生,所以我不確定我是否理解你的意思。 UploadStringAsync返回void。 //編輯看起來像是有人刪除了他的評論 – Loreno

+0

對不起,我以爲你在使用'HttpClient'。您需要訂閱「UploadStringCompleted」事件,該事件一旦完成,將被調用。 – Igor

+2

是否可以切換到'HttpClient',因爲它具有本地異步/等待支持,如https://msdn.microsoft.com/en-us/library/hh138242.aspx。 –

回答

2

WebClient有一個返回過載Task<string>

https://msdn.microsoft.com/en-us/library/hh193920(v=vs.110).aspx

您可以觸發所有請求,然後等待他們Task.WhenAll

public void GetData(string dataToPost) 
{ 
    var url = "some URL"; 
    var url2 = "some other URL"; 

    using (var client = new WebClient()) 
    { 
     client.Headers[HttpRequestHeader.ContentType] = "application/json"; 

     var task1 = client.UploadStringTaskAsync(new System.Uri(url), "POST", dataToPost); 
     var task2 = client.UploadStringTaskAsync(new System.Uri(url2), "POST", dataToPost); 

     var results = Task.WhenAll(task1, task2).Result; 

     foreach (var result in results) 
     { 
      Console.WriteLine("Result is here"); 
      Console.WriteLine(result); 
     } 
    } 
} 

更妙的是,如果你可以改變你的GetData爲async方法,您可以只需awaitTask.WhenAll

1

正如評論中所說,HttpClient是這類任務的更自然的選擇。但是,你仍然可能不知道如何提供認購事件的任務,這可能與TaskCompletionSource<T>來完成,用相當小的改變你的代碼:

private Task<string> GetData(string dataToPost) 
{ 
    var url = "some URL"; 
    var resultSource = new TaskCompletionSource<string>(); 

    using (var client = new WebClient()) 
    { 
     client.Headers[HttpRequestHeader.ContentType] = "application/json"; 

     client.UploadStringCompleted += (s, e) => { 
      Console.WriteLine("Result is here"); 
      Console.WriteLine(e.Result); 

      // this will complete the task 
      resultSource.SetResult(e.Result); 
     }; 

     client.UploadStringAsync(new System.Uri(url), "POST", dataToPost); 
    } 

    return resultSource.Task; 
} 

您還可以設置一個cancellation(帶given token太)和exception(即使與multiple exceptions)在這種情況下,所以它會自然適合您的需求。對於併發事件訂閱的情況,所有三種方法都可以以Try*的方式完成。

另請注意@ Stefanod'Antonio對async method過載的回答。

+0

感謝您的意見,這很有趣。看起來像一個JavaScript的承諾。 – Loreno

+0

C#中的'Task'和Javascript中的'Promise'幾乎相同。 – VMAtm

相關問題