[英]System.Net.WebClient Problems
我正在编写一个必须访问MySQL数据库的程序。 为此,我编写了一个PHP WebService来获取表中的所有值。 我遇到的问题是我正在C#中编写一个函数来获取这些值。 我希望函数等待,直到调用DownloadStringCompleted事件的事件处理程序,然后返回值。 我这样做是这样的:
WebClient client = new WebClient();
client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(DownloadCompletedHandler);
client.DownloadStringAsync(new Uri(Application.Current.Host.Source.AbsoluteUri + "\\PHP\\GetAdmins.php"));
while (DownloadCompleted == false) { }
return DownloadResult;
但这会使程序挂起。
我需要使该部分程序暂停直到DownloadConpleted = true的东西。
我正在运行Visual Studio Ultimate 2010,正在制作Silverlight应用程序,任何帮助将不胜感激。
您可以使用ManualResetEvent
从下载完成处理程序发出完成事件信号,并使主线程等待它:
ManualResetEvent completionEvent = new ManualResetEvent(false);
WebClient webClient = new WebClient();
webClient.DownloadStringCompleted +=delegate(object sender, DownloadStringCompletedEventArgs e)
{
completionEvent.Set();
};
webClient.DownloadStringAsync(new Uri(Application.Current.Host.Source.AbsoluteUri + "\\PHP\\GetAdmins.php"));
completionEvent.WaitOne();
这回答了您的问题,但是它仍然会使UI线程等待-您确实必须与Silverlight保持异步,因此需要一个解决方案,以在DownloadStringCompleted
事件处理程序中更新您的模型-这样您就不必使用拐杖和您的应用程序将性能更好。
您可以使用ManualResetEvent :
public string Download()
{
var manualEvent = new ManualResetEvent(false);
WebClient client = new WebClient();
var result = string.Empty;
client.DownloadStringCompleted += (sender, e) =>
{
if (e.Error != null)
{
result = e.Result;
}
manualEvent.Set();
};
client.DownloadStringAsync(new Uri(Application.Current.Host.Source.AbsoluteUri + "\\PHP\\GetAdmins.php"));
// block while the download is completed and the event is signaled or
// timeout after 30 seconds
if (!manualEvent.WaitOne(TimeSpan.FromSeconds(30)))
{
// timeout
}
return result;
}
请注意,阻塞主线程是一个坏习惯,因为它将冻结UI。 更好的方法是只在下载完成的事件处理程序中处理结果。 并且由于此处理程序是在与UI线程不同的线程上执行的,所以请不要忘记封送将UI更新到主线程的所有调用。
推荐的例子:
public void string Download()
{
var manualEvent = new ManualResetEvent(false);
WebClient client = new WebClient();
client.DownloadStringCompleted += (sender, e) =>
{
if (e.Error != null)
{
Dispatcher.BeginInvoke(() =>
{
ResultLabel.Text = e.Result;
});
}
else
{
Dispatcher.BeginInvoke(() =>
{
ResultLabel.Text = e.Error.ToString();
});
}
};
var url = new Uri(Application.Current.Host.Source.AbsoluteUri + "\\PHP\\GetAdmins.php");
client.DownloadStringAsync(url);
}
这样,您不再阻塞主线程,并且UI保持流畅。 异步操作完成后,您可以使用Dispatcher.BeginInvoke方法整理对UI线程的调用,从而用结果更新UI。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.