在BackgroundWorker的DoWork方法中引发其他事件

时间:2013-11-12 16:41:01

标签: c# multithreading events user-interface backgroundworker

我正在尝试从我的UI在另一个线程上运行一个长时间运行的实例方法,但仍然会将进度报告回GUI线程以更新进度条。我知道有很多方法可以做到这一点以及关于此问题的许多问题。长期运行的实例方法我实际上有两个它自己的事件。它有一个在PropertyChanged上触发的事件,用于报告当前完成的工作&当前需要完成的总工作量。它还有一个OperationCompleted事件。我计划在我的UI中使用BackgroundWorker在一个单独的线程上运行这个长时间运行的方法。我想弄清楚的是:

如果我为PropertyChanged&创建事件处理程序OperationCompleted事件,我可以实现它们来引发BackgroundWorker个事件吗?这是否允许它们全部在后台线程上运行并基本上模拟一个冒泡到UI线程的事件?以下是一个例子:

class GUI : Form
{
     private BackgroundWorker back = new BackgroundWorker();
     back.WorkerReportsProgress = true;
     back.DoWork += new DoWorkEventHandler(myWork);
     back.ProgressChanged += new ProgressChangedEventHandler(myWork_changed);
     back.RunWorkerCompleted += RunWorkerCompletedEventHandler(myWork_completed);

     /* GUI CODE OMITTED */

     private void button_click(object sender, EventArgs e)
     {
          back.RunWorkerAsync();
     }
     private void myWork(object sender, DoWorkEventArgs e)
     {
          Syncer sync = new Syncer();
          sync.PropertyChanged += new PropertyChangedEventHandler(sync_PropertyChanged);
          sync.OperationCompleted += new EventHandler(sync_OperationCompleted);
          sync.LongRunningMethod();

     }
     private void sync_PropertyChanged(object sender, PropertyChangedEventArgs e)
     {
           //calculations & logic as needed
           back.ReportProgress(calculated);
     }
     //might not be necessary to implement because of how BackgroundWorker functions
     private void sync_OperationCompleted(object sender, EventArgs e)
     {
           back.ReportProgress(100);
     }

     private void myWork_changed(object sender, ProgressChangedEventArgs e)
     {
          //update UI progress bar
     }
     private void myWork_completed(object sender, RunWorkerCompletedEventArgs e)
     {
          //tasks needed @ completion such as hide progress bar
     }

Syncer类的事件也会触发与BackgroundWorker的{​​{1}}方法相同的线程吗?这个线程安全吗?批评&另类建议欢迎!

2 个答案:

答案 0 :(得分:1)

从后台工作线程引发的事件将运行并阻塞该线程,并且可以反过来提升也会运行的ReportProgress事件并阻止工作线程,只要它可以访问对BackgroundWorker的引用。

如果您牢记这一点,并使用调用调用来更新UI,它应该可以正常工作。

答案 1 :(得分:1)

Syncer()类事件将从实际引发它们的任何线程触发。这可能是与DoWork()处理程序相同的线程,它可能不是。我们不知道Syncer()类的内部工作方式,因此我们无法从您发布的代码中知道。

然而,从Syncer()事件调用ReportProgress()很好。无论它们触发什么线程,这仍然会导致在主UI线程中引发ProgressChanged()和RunWorkerCompleted()事件(假设BackgroundWorker()是由主UI线程本身创建的;在这种情况下它是)。

您不需要手动调用()任何东西,这就是首先使用BackgroundWorker()的重点......以避免需要这样做。

如果你没有使用BackgroundWorker()并通过其内置事件“冒泡”事件,而是将Syncer()操作包装在手动线程中,那么是的,你需要手动调用()GUI的更新。