2012-03-13 96 views
0

我有一个主要的GUI应用程序,它完成了它在引用程序集中的实际工作。现在,我不会在后台工作人员中完成这项工作,因此它在处理主要用户界面时基本上锁定了它。在我引用的组合中,我添加了很多事件来向主UI表单报告不同的进度。在主UI形式上,我使用这些事件的值更新不同的文本框。我的问题是,首先,处理这些事件的过程似乎要慢得多。那么我应该在辅助线程(从引用的程序集)上触发事件吗?我最初的电话是否应该通过后台工作人员进行引用(静态)?我想在一个单独的线程上报告不同类型的进度,但不确定采用哪种方法来获得最佳性能。我是否需要实现后台工作人员

感谢

回答

1

从你的描述,它听起来就像你会从多线程中获益,因为这将有助于保持UI响应。

而最简单的方法是使用BackgroundWorker。从one of the many samples开始,然后咬下子弹,如果有任何问题,请回到这里。

在回应评论:

从一个BackgroundWorker工作线程的主线程进行沟通的最佳方式是调用BackgroundWorker.ReportProgress方法,它带有一个可选的对象参数userState,你可以用它来打包你想要沟通的数据。

这会导致在主线程上引发BackgroundWorker.ProgressChanged事件 - 并且可以在不需要显式Invoke的情况下处理数据。

如果您已经实施了事件,您必须重新调用ReportProgress而不是提高事件,或者实施某种适配器来处理事件并将它们路由到ReportProgress方法调用。

+0

感谢@Joe,我对BackgroundWorker或多线程没有问题,但我想我更好奇,如果引用的程序集职责是通过BackgroundWorker启动的,并且它们的静态事件是从BackgroundWorker的线程触发的,调用表单在主UI线程上接收它们,还是在Background线程上接收到它们? – ganders 2012-03-13 17:48:58

0

你可以在不同的线程启动的过程(在其它组件的方法),以及处理由它在主窗体上引发的事件。

由于UI不能被另一个线程更新,所以应该将这些事件的代码包装在this.Invoke()中。

例:

private void TheEventRaisedOnAnotherThread(object sender, EventArgs e) 
{ 
    _counter++; 
    this.Invoke(new MethodInvoker(delegate() { TextBox1.Text = _counter.ToString(); })); 
} 
+0

谢谢@matap,所以我只是设置一个辅助线程来调用我的“ReferencedAssembly.Go()”方法。然后,由ReferencedAssembly类引发的事件将通过主UI线程接收,对吧? 辅助线程aka BackgroundWorker – ganders 2012-03-13 17:50:26

+0

如果在新线程上调用ReferencedAssembly.Go,它的事件将在新线程上执行,而不是在主UI线程上执行。因此,这就是为什么你应该使用this.Invoke()更新你的UI。 – 2012-03-13 20:14:50