繁体   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