我有一个我正在做的宠物项目,它有多个工作线程。将所有输出输出到控制台变得越来越难,所以我想开发一个UI,它每个线程都有一个输出区域。我想知道线程向UI发送更新的最佳方式。我有两个想法:
1)当新数据可用时,让每个线程设置一个"DataUpdated“标志,并让UI定期检查新数据。
2)使用UI更新回调(.)创建每个线程方法,以便在新数据可用时调用。
我目前倾向于(2)有两个原因:我不喜欢“检查”每个线程的想法,因为这是我的第一个多线程应用程序,(2)看起来比它可能更简单。我想知道:
发布于 2010-01-19 21:38:21
通过创建BackgroundWorker组件并在其DoWork处理程序中完成工作,您可以轻松地实现(2):
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += /* your background work here */;
bw.ProgressChanged += /* your UI update method here */;
bw.RunWorkerAsync();每个BackgroundWorker都可以通过调用ReportProgress向UI线程报告进度:虽然这主要是为报告有界进程的进度而设计的,但这不是强制性的--如果您的UI更新需要这样的话,您也可以传递您自己的自定义数据。您可以从您的ReportProgress处理程序中调用DoWork。
BackgroundWorker的好处是它为您处理了许多混乱的交叉线程细节。它也符合事件驱动的更新模型,您(正确地)更倾向于显式回调。
发布于 2010-01-19 22:31:05
在大多数情况下,最简单的方法是使用itowlson的答案中所建议的BackgroundWorker组件,如果可能的话,我强烈建议使用这种方法。如果出于某种原因,您不能使用BackgroundWorker组件来实现您的目的,比如您正在使用.Net 1.1开发(yikes!)或者使用紧凑的框架,那么您可能需要使用另一种方法:
使用Winform控件时,您必须避免修改除最初创建控件的线程之外的任何线程上的控件。BackgroundWorker组件为您处理这个问题,但是如果您不使用它,那么您可以而且应该使用在System.Windows.Forms.Control类中找到的InvokeRequired属性和Invoke方法。下面是一个使用此属性和方法的示例:
public partial class MultithreadingForm : Form
{
public MultithreadingForm()
{
InitializeComponent();
}
// a simple button event handler that starts a worker thread
private void btnDoWork_Click(object sender, EventArgs e)
{
Thread t = new Thread(WorkerMethod);
t.Start();
}
private void ReportProgress(string message)
{
// check whether or not the current thread is the main UI thread
// if not, InvokeRequired will be true
if (this.InvokeRequired)
{
// create a delegate pointing back to this same function
// the Invoke method will cause the delegate to be invoked on the main UI thread
this.Invoke(new Action<string>(ReportProgress), message);
}
else
{
// txtOutput is a UI control, therefore it must be updated by the main UI thread
if (string.IsNullOrEmpty(this.txtOutput.Text))
this.txtOutput.Text = message;
else
this.txtOutput.Text += "\r\n" + message;
}
}
// a generic method that does work and reports progress
private void WorkerMethod()
{
// step 1
// ...
ReportProgress("Step 1 completed");
// step 2
// ...
ReportProgress("Step 2 completed");
// step 3
// ...
ReportProgress("Step 3 completed");
}
}发布于 2010-01-19 21:37:28
我也投第二票,但用的是BackgroundWorkers而不是System.Threading.Threads。
https://stackoverflow.com/questions/2097284
复制相似问题