【问题标题】:Exceptions on .Net ThreadPool Threads.Net ThreadPool 线程的异常
【发布时间】:2010-10-14 16:09:19
【问题描述】:

重复:How to catch exceptions from a ThreadPool.QueueUserWorkItem?


我在 .Net ThreadPool 上为大量独立的远程调用排队,这些调用本身调用多个数据库和其他离线资源。通过在 ThreadPool 上排队这些调用,我可以同时运行它们并最小化整体延迟。

private void CompleteAndQueuePayLoads(IEnumerable<UsagePayload> payLoads)
{
    List<WaitHandle> waitHndls = new List<WaitHandle>();
    foreach (UsagePayload uPyLd in payLoads)
    {
        ManualResetEvent txEvnt = new ManualResetEvent(false);
        UsagePayload uPyLd1 = uPyLd ;
        ThreadPool.QueueUserWorkItem(
            delegate
                {
                    if (!uPyLd1 .IsComplete)
                        // IEEDAL.GetPayloadReadings is long running DB call
                        try { IEEDAL.GetPayloadReadings(uPyLd1 ); }
                        catch (IEEAccessException iX)
                        {
                            log.Write(log.Level.Error,
                                  "IEEWSDAL.CompleteAndQueuePayLoads " + 
                                   " Delegate Failed " +
                                  iX.Message, iX);
                            txEvnt.Set();
                            throw;  // this causes parent thread to crash!
                            // was going to try Thread.Abort next ...
                            // Thread.CurrentThread.Abort();
                        }
                    UsageCache.PersistPayload(uPyLd1 );
                    SavePayLoadToProcessQueueFolder(uPyLd1 );
                    txEvnt.Set();
                });
        waitHndls.Add(txEvnt);
    }
    util.WaitAll(waitHndls.ToArray()); //To waitone on > 64 waithandles
}

但是整个批处理需要事务处理,即父线程的输出只需要在所有子线程都成功的情况下才允许继续。我已经将子线程编码为在失败时抛出自定义异常,但我发现这会导致父线程崩溃,因为这些异常无法在父线程中“捕获”...

我已经阅读过 CLR 在发生这种情况时抛出 UnHandledExceptionEvent 的信息,但是我需要在这些子线程排队和生成的方法中“处理”这个异常,以根据成功控制立即的下游处理孩子们的三人……我该怎么办?

【问题讨论】:

    标签: .net exception threadpool unhandled-exception


    【解决方案1】:

    如果线程失败,您可以在 CompleteAndQueuePayLoads 函数的局部变量中标记至少发生一次失败,并添加异常/失败变量以供稍后检查。

    【讨论】:

      【解决方案2】:

      我在当前的项目中经常这样做。我采用的方法是制作我自己的调度程序来接收委托,将其添加到我自己的队列中,然后运行它们以在最后处理同步等。

      我在这种情况下使用的“技巧”是不直接在线程池上调用委托,而是在我的调度程序中调用包装委托并更优雅地处理异常的方法。这样,实际的内部方法调用总是以适当的(对我而言)方式处理。

      当异常发生时,我的调度程序会收到通知并停止调度未来的任务(这是一个不错的奖励),但也会负责告诉调用者有一个异常。

      【讨论】:

        【解决方案3】:

        您可以查看 3.5 的并行库扩展。您可以在代码块上使用 Parallel.Invoke 来完成您正在尝试的操作。

        【讨论】:

        • 是的,我最近才看到,但我已经使用一个等待句柄数组解决了这个问题,方法是遍历数组以查看所有这些都已被释放..
        猜你喜欢
        • 1970-01-01
        • 2014-12-31
        • 1970-01-01
        • 1970-01-01
        • 2010-10-02
        • 2017-12-17
        • 1970-01-01
        • 2011-07-07
        • 2023-03-24
        相关资源
        最近更新 更多