C#BackgroundWorker偶尔需要很长时间才能启动

时间:2012-09-09 16:56:37

标签: c# multithreading backgroundworker

我发现使用BackgroundWorker存在问题。发生的事情是BackgroundWorker进程可以正常工作,然后有时需要大约40-50秒才能开始。

两台机器上出现问题。 BackgroundWorker操作全天工作正常,然后在下午这个问题开始出现,这个过程需要40秒而不是1秒,但只是偶尔发生。你可以做到5个很好,第6个需要40秒。然后你可以做另外5罚款。如果它开始花费的时间超过一秒,你可以按下workingDialog上的取消并立即再次执行,它会起作用。在进一步检查时,工作人员似乎没有立即启动DoWork方法。

我可能会用尽线程吗?或者我是如何处理BackgroundWorker的?代码如下;

using (workingDialog = new Dialogs.WaitDialog()) {
    StartThreadedWork(MyDoWorkMethod, customerID);

    // if user presses cancel button
    if (workingDialog.ShowDialog() == System.Windows.Forms.DialogResult.Cancel) {
        m_Worker.RunWorkerCompleted -= ThreadFinished;
    }
}
m_Worker.Dispose();
m_Worker = null;

'StartThreadedWork'方法如下;

private void StartThreadedWork(DoWorkEventHandler method, int customerID) {
    m_Worker = new BackgroundWorker();
    m_Worker.DoWork += method;
    m_Worker.RunWorkerCompleted += ThreadFinished;
    object[] parameters = new object [] {customerID };
    m_Worker.RunWorkerAsync(parameters);
}

最后,分配给DoWork事件处理程序的方法是;

private void ThreadSyncing(object sender, DoWorkEventArgs e) {
    object[] parameters = e.Argument as object[];
    int customerID = (int)parameters[0];
    Customer resultCustomer = new Customer(FormsManager.Instance.BillingWebService.Customer_GetByCustomerID(customerID, CustomerSyncOption.Default));
    e.Result = resultCustomer;
}

触发RunWorkerCompleted事件后,对话框结果将设置为OK,对话框将关闭。

任何关于此的指针都会非常受欢迎!

感谢,

2 个答案:

答案 0 :(得分:2)

你怎么知道实际上BGW的开始被推迟了?你没有给出任何反馈,你只能看到它完成了。看起来您正在使用Web服务,服务器没有响应或完成请求,40秒没有异常。默认的tcp / ip连接超时为45秒。

ThreadPool调度程序可以发挥作用,它会尝试将执行TP线程的数量限制为机器具有的cpu核心数。然而,延迟40秒是一个沉重的角落案例。调度程序允许另一个TP线程启动,如果现有的线程没有完成,每秒两次。因此,您将拥有80个活动TP线程,以产生类似的延迟。

有一点值得注意的是你使用的对话框,它实际上并没有做任何事情来阻止工作线程。它只是放弃它。因此,如果服务器没有响应且用户不耐烦,您可能会积累。四次敲击她的脚后反复按下取消按钮。 确实导致延迟不断增加。您应该使用CancelAsync()方法并使用CancellationPending属性实现取消逻辑。但是,对于网络服务而言,这通常不容易。

通过提供更好的反馈来解决这个问题。当用户取消时,取消订阅RunWorkerCompleted事件。只需设置一个标志,指示最后一个请求被取消。在UI中显示Web服务不可用,直到工作人员完成。包括不允许用户再次启动Web服务请求。

答案 1 :(得分:1)

BackgroundWorker使用.Net线程池执行其DoWork方法。

如果你在线程池上加载太多负载,一些工作项将被延迟,直到它有一个可用于处理它们的线程。