2013-08-01 72 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 –