我使用用户名和密码调用此静态登录方法。我希望它等待,直到downloadstringasync完成。对于我的生活,我不能让它等待。
我尝试过oldschool
while(wc.IsBusy){} //Which froze
还尝试了各种甚至没有编译的异步废话
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);
}
答案 0 :(得分:3)
首先,您永远不应该等待来完成异步操作。而是在函数完成后继续执行。
编辑:您必须在此处添加NuGet包Microsoft.Bcl.Async。
现在,由于您使用的是Windows Phone 8,因此可以安全地在此处使用async:
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);
}
}
Async 必须编译,因为它才有效。如果您遇到问题,请在此处再次使用您的代码段。
如果你想要定位Windows Phone 7,添加上面提到的NuGet包,你就可以毫无问题地编译它。
答案 1 :(得分: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););
};
}
答案 2 :(得分:1)
如果您通过旋转while
循环或使用ManualResetEvent.WaitOne
强制在UI线程中等待,那么您实际上是在使应用程序陷入僵局。在某些时候网络调用似乎需要触摸UI线程,但你已经冻结它=死锁。
像这样冻结UI线程在许多其他方面也很糟糕(不会处理任何触摸事件,没有屏幕更新等)。
最好使用HttpClient for Windows Phone并使用async / await模式。您可以从NuGet下载此软件作为Microsoft.Net.Http软件包。
答案 3 :(得分:1)
您可以借助Async和Await方法重写现有的WebClient方法
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;
}
通过这样做,你可以等待你的电话,直到回调回来。这是实现功能的最有效和最新的方法