Update GUI from background worker or event

纵然是瞬间 提交于 2019-12-13 02:57:31

问题


I want to understand how I can update my GUI with a simple text string on a regular basis. Essentially, I'm writing a twitter application which regularly polls twitter for updates. I want the contents of the update to be shown in a text block, one by one on a constant loop.

In order to keep the GUI responsive I need to perform the query in a background worker thread, however updating the GUI from this thread is not possible. As a learner, I'm struggling implement a way of updating the GUI by using events.

In my code below, I appreciated 'MainWindowGoUpdate' is going to be on the 'wrong thread' but how can I get the GUI thread to listen for the event?

A pointer appreciated.

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";
  }  
 }

回答1:


I will try these change:
In your UpdateTimeLine add

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

In startTimelineUpdater_DoWork remove these lines

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

and insert these:

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

finally add the progress event

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

Now you can leave only the call to UpdateTimeLine and remove the MainWindowGoUpdate method




回答2:


You can use the Dispatcher class:

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

However in your case I would collect the results from the BackgroundWorker in a local variable and then change your label to loop through the results based on a WPF Timer object.




回答3:


You can use the Dispatcher to update your GUI. Check this blog post for a rather good example on how to do it.




回答4:


Where you

  txtb_timeline.Text = "should not see this";

Is where you get the results. Results will be in e.Result And you can pack e.Result with multiple properties.

If you want to get intermediate results you can use the progress.



来源:https://stackoverflow.com/questions/10019960/update-gui-from-background-worker-or-event

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!