2

我使用 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();
    }

如您所见,我在完成后重新启动了工人。现在这适用于单个后台工作人员。

现在我想要一个集合,每个项目都应该执行这个任务。然而,有了上面的概念,它只会在第一个启动的worker中继续运行,因为它会重新启动worker。我在想,也许 Timer 的组合可以解决这种情况,为其他工作线程提供方式。

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

编辑 1:澄清:我面临的问题是,我需要用自己的 BackgroundWorker 管理每个集合。我正在考虑一个计时器,以定期从每个项目中触发请求。这就是我卡住的地方。

编辑 2:查看我自己的答案,我没有解决这个问题,但发现我可以配合计时器来获得我想要的东西。

编辑 3:澄清(另一种尝试,我不擅长)我想要实现的目标:我有跟踪对象,用于 gps 跟踪。我想跟踪一大堆,所以每个跟踪设备一个对象。他们都需要经常轮询。我为单个测试对象设置了 BackgroundWorker。我喜欢后台工作人员在完成时告诉我的方式。但我无法让它与所有跟踪对象一起工作。

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

4

6 回答 6

4

这些可能有多少?您应该小心在集合中的项目和线程之间创建 1:1 关系。另一位编码员可能会出现并超出您的计划扩展此集合。

对于这样的事情,我通常喜欢只使用一个线程和一个队列 - 所以事件只是将需要完成的工作放在 ConcurrentQueue 中,如果没有运行,线程就会启动,并在排队的工作中搅动,直到它完成无事可做,死去。下次有更多工作发生时,该事件将检查线程是否正在运行并启动它。

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

于 2009-09-22T01:22:03.287 回答
1

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

然后就不会反对运行多个 Bgw,尽管您可能看不到很大的速度优势。

于 2009-08-18T08:18:05.793 回答
1

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

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

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

那么显然,您需要相应地管理BackgroundWorker' 的集合。

于 2009-08-18T09:14:03.997 回答
1

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

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

无休止地执行此操作并使用取消来停止该线程。

问候。

于 2009-09-21T16:11:40.390 回答
0

当你有多个耗时的任务要同时执行时,我建议你使用线程池

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

于 2009-08-18T08:01:35.357 回答
0

由于到目前为止没有人这样做,我将使用计时器方法。我试图将两者(BackgroundWorker 和 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);
    }

这就是 John Saunders 对类似(但不同)问题的建议。它似乎完成了这项工作。有一个同步的WriteData()HttpWebRequest,所以它可以处理超时。

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

注意:WebRequest 的异步方法不起作用,我试过了。到目前为止,我不知道是否这是服务器的一种方式。

于 2009-08-18T11:44:45.157 回答