2014-02-23 148 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