BackgroundWorker和Timer,一次处理一个项目

时间:2009-06-22 22:21:15

标签: c# winforms backgroundworker

我的应用监控用户可以上传文件的目录。检测到新文件时,会将其添加到队列中。我有一个运行队列的计时器,并确定文件是否已完成上传。如果有任何文件已完成,则需要使用最新文件并开始运行后台任务(使用BackgroundWorker)。

我的问题是我不知道在后台任务运行时如何处理计时器。例如,如果计时器设置为10秒并且后台工作程序仍在工作,我希望计时器跳过另一个后台工作程序的执行,直到下一次迭代。

此外,每个任务的信息都存储在Queue(ListView控件)中,我将ListViewItem传递给后台worker。如果传递ListViewItem有任何副作用,我很好奇。

谢谢!

6 个答案:

答案 0 :(得分:1)

您可以将准备好处理的文件存储在另一个队列中(例如Queue< string>)并让BgWorker不断轮询该队列。您可能也会获得更好的性能,减少空闲时间。您必须保护队列(使用监视器)并让BgWorker在队列为空时使用Monitor.Wait。

要获得一个想法,请在this question上查找Marc Gravell的答案。

答案 1 :(得分:0)

如果没有看到您正在谈论的代码,真的很难回答这个问题。但是,如果必须同步多个异步事件(检测到文件已下载,将文件添加到队列,处理队列),我建议创建一个执行所有任务的BackgroundWorker。然后,您的工作人员可以轻松测试每个步骤的状态。我会避免创建多个线程并尝试同步它们,这是非常有问题的。

我也不会将任何后台任务信息存储在UI数据结构中(如ListView控件)。在BackgroundWorker中创建一个回调或事件,当需要显示内容时,它将提醒用户界面。

答案 2 :(得分:0)

BackgroundWorker.IsBusy Property您要找的是什么?

答案 3 :(得分:0)

您可以做的最简单的事情是在BackgroundWorker中完成所有工作(包括检查文件夹):检查您是否有事可做,如果是,则执行此操作,如果没有,请使用睡眠(时间)或WaitOne(时间) )暂停线程一段时间。

我认为你不需要这里的线程安全队列,因为无论如何都要异步更新文件夹。所以你只需要一个线程,你需要一种方法来阻止它。这就是AutoResetEvent.WaitOne(时间)优于Sleep(时间)的原因 - 您可以从主线程发出事件信号,以便更早地结束您的后台工作。

答案 4 :(得分:0)

在Timer.Tick处理程序上,检查BackgroundWorker.IsBusy属性以确定它是否已准备好进行其他工作。如果没有,只需跳过工作并等到下一个Tick。

答案 5 :(得分:0)

您可以创建一个线程队列,您可以在其中放置待完成工作。您的后台工作人员在队列中拉出项目并执行工作。 有些事情需要考虑:

  • 队列需要是线程安全的,如果队列为空,您很可能希望后台工作程序阻塞,并在项目可用时唤醒。我确定somone已经做了这么好的队列。
  • 您发布到队列中的项目将在另一个线程(后台工作者)中进行操作。确保以线程安全的方式完成此操作(例如,不要将项目发布到主应用程序和后台工作程序都将更改的队列中)。

另一种更简单的方法是

  • 对应用程序中的项目进行排队。第一次开始背景工作。
  • 当你完成后台工作完成的事件时,从队列中选择下一个项目并使用此项目再次启动后台工作。
  • 您仍然需要关心线程安全。当你向backworkworker发送一个项目时,确保只有backgroundworker对它进行操作(例如,如果你只是发送它的字符串,则发送一个字符串的副本)

我没有完全按照你的计时器。如果后台工作人员完成了你应该得到一个事件,你会知道它已经完成,不需要计时器来检查它。