在集合项中使用BackgroundWorker

时间:2009-08-18 07:54:58

标签: c# multithreading backgroundworker

我使用Backgroudworker做一些工作以完成一些耗时的任务。

public void ConnectDataProvider()
    {
        bgw = new BackgroundWorker();
        bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);
        bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);

    }

另一种方法启动后台工作程序:

public void StartPolling()
    {
        bgw.RunWorkerAsync();
    }

然后我做了事件处理:

void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // do it over again
        StartPolling();
    }    

void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        // do work
        WriteData();
    }

正如你所看到的,我在工作结束后开始工作。现在这适用于单个背景工作者。

现在我想要一个集合,每个项目都应该执行此任务。然而,根据上面的概念,它将继续在第一个工作者开始运行,因为它启动了工作人员。我在想,也许一个Timer组合可以解决这种情况,让其他工作者的线程方式。

BackgroundWorker仍然是一个不错的选择吗?像我一样重用BackgroundWorker是否常见?

编辑1:要理解:我面临的问题是,我需要使用自己的BackgroundWorker来管理集合。我正在考虑一个计时器,定期从每个项目中提出请求。这就是我被困住的地方。

编辑2:看到我自己的答案,我没有解决这个问题,但发现我可以跟定时器一起去获得我想要的东西。

编辑3:澄清(另一次尝试,我不擅长)我想要实现的目标:我有跟踪对象,用于gps跟踪。我想跟踪它们中的一大堆,因此每个跟踪设备都有一个对象。他们都需要经常接受调查。我为一个测试对象设置了BackgroundWorker。我喜欢他们的方式,背景工作者会告诉我它什么时候完成。但我无法使用所有跟踪对象。

现在每个跟踪对象都有自己的计时器。这个计时器产生一个新线程并完成耗时的工作(我将其命名为DoWrite)。不需要BackgroundWorker,因为我处理了计时器,然后创建了一个新的计时器。就是这样。

6 个答案:

答案 0 :(得分:4)

这些可能有多少?您应该小心在集合和线程中的项之间创建1:1关系。另一个程序员可能会比你计划的更多地扩展这个系列。

对于这样的事情,我通常只想使用一个线程和一个队列 - 因此事件只需要在ConcurrentQueue中完成需要完成的工作,如果没有运行则线程启动,并通过排队进行搅拌工作,直到事情要做,并死亡。下次更多工作进入时,将检查线程是否正在运行并启动它。

它更便宜,因为如果有很多事情发生,你只运行一个线程而不是停止并启动很多线程,或者如果进行的很少,那么一个线程几乎从不运行。

答案 1 :(得分:1)

如果你只是在Dowork()中放置一个while()循环,那么你的解决方案会更合乎逻辑,也许有一点Sleep()。

然后不会反对运行多个Bgw,尽管你可能看不到速度上的好处。

答案 2 :(得分:1)

您可以完全按照您的描述进行操作 - 只需确保将相关后台工作人员的引用传递给StartPolling,因此:

void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // do it over again
    StartPolling((BackgroundWorker)sender);
}

public void StartPolling(BackgroundWorker worker)
{
    worker.RunWorkerAsync();
}

显然,你需要相应地管理BackgroundWorker的集合。

答案 3 :(得分:1)

为什么不使用progresschanged事件?您可以使用userstate对象传递数据。

在工作中只是池化设备,并且在更改过程中将数据发送到UI线程。

无休止地使用取消来停止该线程。

问候。

答案 4 :(得分:0)

如果您要在同一时间执行多个耗时的任务,我建议您使用线程池

http://msdn.microsoft.com/en-us/library/ms973903.aspx

答案 5 :(得分:0)

由于到目前为止没有人这么做,我会投入计时器方法。我尝试将两者结合起来(BackgroundWorker和Timer),但这没有用。

我想要一种允许多个实例按线程请求数据的机制。另外,我想要介于两者之间。

所以在尝试之后,我认为我只能与Timer方法相处:

public void ConnectDataProvider()
    {
        timer = new Timer(new TimerCallback(tCallback), null, 0, Timeout.Infinite);            
    }

private void tCallback(object state)
    {
        timer.Dispose();
        // time consuming task
        WriteData();
        timer = new Timer(new TimerCallback(tCallback), null, 5000, Timeout.Infinite);
    }

这就是约翰·桑德斯对类似(但不同)问题的建议。它似乎做了这个工作。 WriteData()具有同步HttpWebRequest,因此它可以处理超时。

我现在的问题是:计时器对象的新实例化有多贵?我的意思是:我们有更好的方法来实现这个目标吗?

注意:WebRequest的异步方法不起作用,我试过了。到目前为止我没有任何线索,如果这是服务器的一种方式。