2014-02-23 63 views
1

我试图创建一个启动然后GUI应用程序后,它已经显示我希望它运行使用Web客户端()其他功能,一旦做它的查询是应该输出到页面上的标签。我已经尝试过使用显示和其他一些事件,但是所有这些事件在完成查询之前都停止加载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(); 
    } 

是不是我做错了吗?有没有更好的方法来完成这一点?我一直坚持这几个小时,并找不到任何我需要它做的事情。

回答

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();

+0

这工作得很好,最初得到了一个混蛋,因为我无法调用bw.RunWorkerAsync();从表单中出现的事件出于某种原因,但是我在声明之后立即放置它,并且它完美地工作。非常感谢你! – zfb

1

你正在尝试从另一个线程更新UI线程上的某些内容,这是行不通的。你可以创建一个委托来更新文本,但这是一个简单的方法。

this.Invoke((MethodInvoker) delegate { systemStatusLabel.Text = "System is up"; }); 
+0

我真的很抱歉,但我只是进入C#,并没有指定任何细节,像我会在哪里调用这个?以及如何将更新发送给它? – zfb

+2

Avi的答案要完整得多,也是一个更好的设计方法,我会采用这种方法。但是,为了完整起见......如果您需要从另一个线程更新主UI线程上的某些内容,而不是像'label1.Text =“Test”;(这会失败),您可以使用上面的代码,它将创建一个在主UI线程上运行的委托。 –

0

The asynchronous programming model with async and await提供易于理解和维护的编码方式。

没有必要再异步工作管理器(如BackgroundWorker)ohter比BYT语言和符合的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!"; 
    } 
} 

Altough的WebClientTaskAsync后缀的方法符合编码这种新的方式,我会推荐您使用以这种新的编码方式开发的HttpClient

+0

那么我专注于WebClient与HttpClient的原因是HttpClient(异步)的响应速度比WebClient(sync)慢50倍。来自WebClient的不到1秒响应对我的吸引力远远大于10秒HttpClient(异步)或〜7秒HttpClient(同步)。然而,我会考虑尝试异步方法,导致我的第一次尝试混淆了我。 – zfb

+0

您是否尝试过使用[Fiddler](http://www.fiddlertool.com/)查看HTTP通信是否相同?最后,它只是一对“HttpWebRequest”和“HttpWebResponse”实例。 –

+0

我还没有,这很有趣。我不知道为什么它更慢我知道结果已经发现并且不想花费太多时间寻找到底为什么,只是想要结果。 – zfb