我正在尝试创建一个启动GUI的应用程序,然后它已经显示我希望它运行另一个使用WebClient()的函数,一旦它执行它的查询,它应该输出到页面上的标签。我已尝试使用show和其他一些事件,但所有这些事件都会在完成查询之前停止加载GUI。
我尝试过使用一个线程并且它不允许更新标签,因为它在不同的线程上,我尝试了异步,但由于某种原因无法获得结果,现在我正处于中间位置尝试后台工作者,我没有收到任何错误,但标签也没有得到更新。
现在我有一些看起来像这样的东西
public project()
{
InitializeComponent();
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += querysite;
}
private void querysite(object sender, DoWorkEventArgs e)
{
WebClient myWebClient = new WebClient();
myWebClient.Headers.Add("user-agent", "libcurl-agent/1.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
byte[] myDataBuffer = myWebClient.DownloadData("http://example.com/SystemStatus");
string download = Encoding.ASCII.GetString(myDataBuffer);
if (download.IndexOf("is online") !=-1)
{
systemStatusLabel.Text = "System is up";
}
else
{
systemStatusLabel.Text = "System is down!";
}
throw new NotImplementedException();
}
我有什么问题吗?有没有更好的方法来实现这一目标?我已经被困在这几个小时了,找不到任何可以做我需要做的事情。
答案 0 :(得分:2)
我稍微修改了您的代码,使用BackgroundWorker
我还允许自己在查询站点的逻辑操作和更新GUI之间做一些分离
这应该适合你:
public project()
{
InitializeComponent();
BackgroundWorker bw = new BackgroundWorker() { WorkerReportsProgress = true };
bool isOnline = false;
bw.DoWork += (sender, e) =>
{
//what happens here must not touch the form
//as it's in a different thread
isOnline = querysite();
};
bw.ProgressChanged += (sender, e) =>
{
//update progress bars here
};
bw.RunWorkerCompleted += (sender, e) =>
{
//now you're back in the UI thread you can update the form
if (isOnline)
{
systemStatusLabel.Text = "System is up";
}
else
{
systemStatusLabel.Text = "System is down!";
}
};
}
private bool querysite()
{
WebClient myWebClient = new WebClient();
myWebClient.Headers.Add("user-agent", "libcurl-agent/1.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
byte[] myDataBuffer = myWebClient.DownloadData("http://example.com/SystemStatus");
string download = Encoding.ASCII.GetString(myDataBuffer);
bool isOnline = download.IndexOf("is online") != -1;
return isOnline;
}
如果要完成查询,则需要调用bw.RunWorkerAsync();
。
答案 1 :(得分:1)
您正在尝试从其他线程更新UI线程上的某些内容,这将无法解决。您可以创建一个委托来更新文本,这是一种简单的方法来实现它。
this.Invoke((MethodInvoker) delegate { systemStatusLabel.Text = "System is up"; });
答案 2 :(得分:0)
The asynchronous programming model with async
and await
提供且易于理解和维护的编码方式。
不需要另外的异步工作管理器(比如BackgroundWorker
),而不需要语言和符合API提供的工作管理器。
假设某些UI事件触发了工作的开始,您所要做的就是:
private async void MyEvent(object sender, EventHandler e)
{
systemStatusLabel.Text = await GetSystemStatusAsync();
}
private async Task<string> GetSystemStatusAsync()
{
WebClient myWebClient = new WebClient();
myWebClient.Headers.Add("user-agent", "libcurl-agent/1.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
var myDataBuffer = await myWebClient.DownloadDataTaskAsync("http://example.com/SystemStatus");
string download = Encoding.ASCII.GetString(myDataBuffer);
if (download.IndexOf("is online") !=-1)
{
return "System is up";
}
else
{
return "System is down!";
}
}
尽管WebClient
的新 TaskAsync 后缀方法符合这种新的编码方式,但我建议您使用以这种新方式开发的HttpClient记住编码。