2013-08-01 101 views
-2

我正在用用戶名和密碼調用此靜態登錄方法。我希望它等待直到下載字符串同步完成。對於我這個嚇人的生活,我無法讓它等待。如何使回撥呼叫等待異步完成c#

我試過老校友

while(wc.IsBusy){} //Which froze 

也嘗試了各種異步廢話說didnt甚至編譯

public static dbObj Login(String username, String password) 
    { 
     dbObj ret = new dbObj(); 
     String rawWebReturn = ""; 
     ret.propBag.Add(_BAGTYPE,returnTypes.Login.ToString()); 
     DateTime date = DateTime.Now; 
     WebClient wc = new WebClient(); 
     wc.DownloadStringAsync(new Uri(baseLoginURI + "uname=" + username + "&pword=" + password + "&date=" + date.ToString())); 


     wc.DownloadStringCompleted += (s,e) => {           
            if(e.Error!=null) 
             rawWebReturn = e.Error.Message; 
            else 
             rawWebReturn = e.Result; 
           }; 
     return parseWebReturn(rawWebReturn,ret);    
    } 
+2

如果你希望它是同步的,爲什麼不直接調用同步方法'DownloadString'? –

+0

因爲它不存在於Windows手機。 –

+3

感謝您澄清平臺。這告訴你一些事情。你不應該試圖阻止。 –

回答

3

首先,你永遠不應該永遠等待等待完成異步操作。相反,在函數完成後繼續執行。

編輯:你必須在這裏添加NuGet包Microsoft.Bcl.Async

現在,因爲你使用的是Windows Phone 8的,你可以放心地使用異步這裏:

public static async dbObj Login(String username, String password) 
    { 
     dbObj ret = new dbObj(); 
     String rawWebReturn = ""; 
     ret.propBag.Add(_BAGTYPE, returnTypes.Login.ToString()); 
     DateTime date = DateTime.Now; 
     WebClient wc = new WebClient(); 
     try 
     { 
      var result = await wc.DownloadStringTaskAsync(new Uri(baseLoginURI + "uname=" + username + "&pword=" + password + "&date=" + date.ToString())); 
      return parseWebReturn(result, ret); 
     } 
     catch (Exception e) 
     { 
      return parseWebReturn(e.Message, ret); 
     } 
    } 

異步必須編譯,因爲它只是工作。如果您遇到問題,請在此處再次提問您的代碼段。

如果您想要定位Windows Phone 7,請添加上面提到的NuGet包,您將可以毫無問題地編譯它。

+0

在Web客戶端中沒有用於Windows Phone的下載字符串任務Ascync –

+1

添加參考NuGet包** Microsoft.Bcl.Async **。 –

+0

謝謝,下班回家時我會試一試! –

1

如果需要,直到異步操作完成的阻塞線程,你可以使用ManualResetEvent,像這樣:

ManualResetEvent wait = new ManualResetEvent(false); 

wc.DownloadStringCompleted += (s,e) => {           
    // ... 

    // allow to proceed 
    wait.Set(); 
}; 

// wait until Set 
wait.WaitOne(); 

return parseWebReturn(rawWebReturn,ret); 

一般來說,你不想阻塞線程,而是使用回調。你可以通過提供的,而不是返回值的Action代表:

public static void Login(String username, String password, Action<dbObj> callback) 
{ 
    // ... 

    wc.DownloadStringCompleted += (s,e) => {           
           if(e.Error!=null) 
            rawWebReturn = e.Error.Message; 
           else 
            rawWebReturn = e.Result; 

           Callback(parseWebReturn(rawWebReturn, ret);); 
          }; 
} 
+0

我重新希望您的第一個解決方案能夠正常工作。然而,它只是掛在waitone :-(對於你的第二個解決方案,返回類型必須是dbObj –

+0

@AMR你確定「DownloadStringCompleted」實際上被觸發嗎? – McGarnagle

+0

它沒有被調用,因爲它掛在WaitOne上 –

1

如果強制在UI線程或者通過紡while循環或使用ManualResetEvent.WaitOne那麼你實際上是死鎖您的應用程序等待。網絡調用在某些時候似乎需要觸摸UI線程,但是您已經凍結了它=死鎖。

像這樣凍結UI線程在許多其他方面也是不好的(沒有觸摸事件將被處理,沒有屏幕更新等)。

你會更好使用HttpClient for Windows Phone,並使用異步/等待模式。你可以從NuGet下載它作爲Microsoft.Net.Http包。

1

您可以用異步和等待方法的東西幫助像這樣的

public Task<string> GetRssFeed(string feedUrl) 
{ 
     var tcs = new TaskCompletionSource<string>(); 
     var client = new WebClient(); 
     client.DownloadStringCompleted += (s, e) => 
     { 
      if (e.Error == null) 
      { 
        tcs.SetResult(e.Result); 
      } 
      else 
      { 
        tcs.SetException(e.Error); 
      } 
     }; 

     client.DownloadStringAsync(new Uri(feedUrl)); 
     return tcs.Task; 

}

這樣做,你可以等待你的電話,直到回調回來重寫現有的WebClient的方法如此。這是實現你的功能的最有效和最新的方式。

+2

是的,這是實現功能的最佳方式。 –

+0

除了這是Windows Phone,並沒有下載字符串完成 –

+2

是的是:http://msdn.microsoft.com/en-us/library/system.net.webclient.downloadstringcompleted(v=vs.95)。 aspx。支持:Windows Phone OS 7.1,Windows Phone OS 7.0 –