繁体   English   中英

System.Net.WebClient问题

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM