关于gui的许多简短任务

时间:2012-08-10 11:10:49

标签: c# multithreading user-interface .net-4.0 backgroundworker

当我必须做很多与GUI合作的简短任务时,我是否应该为每个任务或其他解决方案使用另一个BackgroundWorker

修改

我的意思是每5秒更新一次datagridview(200行x 50列)中的每个单元格。每个单元都存储图像。

2 个答案:

答案 0 :(得分:2)

当我处理许多小任务时,我倾向于发现ThreadPool是处理它们的好方法。您可以在后台线程上调度委托,如下所示:

ThreadPool.QueueUserWorkItem(new WaitCallback(MyThreadProc));

您还可以将对象传递给线程作为其状态,考虑将对象作为参数的委托。你可以这样称呼:

ThreadPool.QueueUserWorkItem(new WaitCallback(MyThreadProc), state);

其中state是某个对象,你的线程知道如何处理。

修改ThreadPool方法适用于您的方案。只需确保必须在GUI线程上调用任何更改GUI的代码,否则您将获得一些跨线程异常。

答案 1 :(得分:2)

BackgroundWorker更适合长时间运行的任务,你想要ThreadPool之类的东西。这是一个非常粗略的例子:

QueueUserWorkItem允许您指定一个worker方法并传入一个对象以供该方法使用。

ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), object);

然后你会得到所有魔法发生的DoWork方法:

public void DoWork(object sender)
{
     object s = (object)sender;

     this.Invoke(new ThreadDone(ReportProgress), result);
}

请注意对this.Invoke(new TaskDone(ReportProgress));的调用这会安全地调用主线程上运行的代码,以使用DoWork中处理过的数据更新您的UI。这是通过私人代表完成的:

private delegate void ThreadDone(object yourObject);

哪个会打电话:

private void ReportProgress(object yourObject)
{
       //update UI
}

您也可以通过跟踪Interlocked计数器对象来检查任务何时完成,例如。

foreach (string s in strings)
{
      ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork), s);
      Interlocked.Increment(ref workItems);
}

然后在单个线程完成时递减workItems并在workItems == 0

时进行简单检查
Interlocked.Decrement(ref workItems);

if (workItems == 0)
{
       this.Invoke(new TaskDone(WorkComplete));
}

希望这有帮助。