簡體   English   中英

從后台工作者或事件更新 GUI

[英]Update GUI from background worker or event

我想了解如何使用簡單的文本字符串定期更新我的 GUI。 本質上,我正在編寫一個 twitter 應用程序,它定期輪詢 twitter 以獲取更新。 我希望更新的內容顯示在一個文本塊中,一個一個地循環顯示。

為了保持 GUI 響應,我需要在后台工作線程中執行查詢,但是無法從該線程更新 GUI。 作為一名學習者,我正在努力實現一種通過使用事件來更新 GUI 的方法。

在我下面的代碼中,我意識到“MainWindowGoUpdate”將出現在“錯誤的線程”上,但是我怎樣才能讓 GUI 線程監聽事件呢?

一個指針表示贊賞。

public partial class MainWindow : Window
{
  public MainWindow()
  {
    public static event UpdateTimeLineEvent _goUpdate;

    public static string TheTimeLine;
    UpdateTimeLine();
  }

  private void UpdateTimeLine()
  {        
   txtb_timeline.Text = "Updating...";

   BackgroundWorker startTimelineUpdater = new BackgroundWorker();
   startTimelineUpdater.DoWork += new DoWorkEventHandler(startTimelineUpdater_DoWork);
   startTimelineUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(startTimelineUpdater_RunWorkerCompleted);
   startTimelineUpdater.RunWorkerAsync();        
  }

  void startTimelineUpdater_DoWork(object sender, DoWorkEventArgs e)
  {
    while (true)
    {
      Xtweet getSQL = new Xtweet();
      var sqlset = getSQL.CollectLocalTimelineSql();

      int i = 0;
      while (i < 10)
      {
        foreach (var stringse in sqlset)
        {
          StringBuilder sb = new StringBuilder();

          sb.Append(stringse[0] + ": ");
          sb.Append(stringse[1] + " @ ");
          sb.Append(stringse[2]);

          sb.Append("\n");

          TheTimeLine = sb.ToString();

          _goUpdate += new UpdateTimeLineEvent(MainWindowGoUpdate);
          _goUpdate.Invoke();

          Thread.Sleep(10000);
          i++;
        } 
      } 
    }        
  }
  void MainWindowGoUpdate()
  {
    txtb_timeline.Text = TheTimeLine;
  }
  void startTimelineUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  {
    txtb_timeline.Text = "should not see this";
  }  
 }

您可以使用調度員 class:

Dispatcher.BeginInvoke(
    DispatcherPriority.Input, new Action(() => 
    { 
        //update UI
    }));

但是,在您的情況下,我會在局部變量中收集來自 BackgroundWorker 的結果,然后更改您的 label 以基於 WPF Timer object 循環遍歷結果。

您可以使用 Dispatcher 來更新您的 GUI。 查看此博客文章以獲得有關如何執行此操作的一個很好的示例。

你在哪里

  txtb_timeline.Text = "should not see this";

是您獲得結果的地方。 結果將在 e.Result 中,您可以將 e.Result 與多個屬性打包在一起。

如果你想獲得中間結果,你可以使用進度。

我會嘗試這些改變:
在您的 UpdateTimeLine 添加

 startTimelineUpdater.WorkerReportsProgress = true;
 startTimelineUpdater.ProgressChanged += new ProgressChangedEventHandler
                                      (startTimelineUpdater_ProgressChanged);

在 startTimelineUpdater_DoWork 中刪除這些行

TheTimeLine = sb.ToString();  
_goUpdate += new UpdateTimeLineEvent(MainWindowGoUpdate);  
_goUpdate.Invoke();  

並插入這些:

BackgroundWorker bkgwk = sender as BackgroundWorker;
bkgwk.ReportProgress(0, sb.ToString());

最后添加進度事件

private void startTimelineUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
   txtb_timeline.Text = e.ObjectState.ToString();
}

現在您可以只保留對 UpdateTimeLine 的調用並刪除 MainWindowGoUpdate 方法

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM