2009-03-20 2 views
4

Дубликата: How to catch exceptions from a ThreadPool.QueueUserWorkItem?Исключение на .Net Threadpool Тема


Я очередь несколько делегатов на .Net ThreadPool для большого количества независимо Remoting вызовов, которые сам называют несколько баз данных и другие автономные ресурсы. Путем очереди этих вызовов в 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 
} 

Но вся партия должна быть обработана транзакционно, И.Е., выход Parent Thread должно быть разрешено только действовать, если все дочерние потоки были успешными. Я закодировал дочерний поток, чтобы создать обычное исключение, когда оно потерпело неудачу, но я обнаружил, что это приводит к сбою родительского потока, поскольку эти исключения не могут быть «пойманы» в родительском потоке ...

Я читал об ошибке UnHandledExceptionEvent от CLR, когда это произойдет, но мне нужно «обработать» это исключение в методе, в котором эти дочерние потоки находятся в очереди и порождены, чтобы контролировать немедленную обработку по потоку, основанную на успехе дочерних триад. Как мне это сделать?

ответ

2

Я делаю это в своем текущем проекте. Подход, который я принял, состоял в том, чтобы создать собственный планировщик, который принимает делегата, добавляет его в мою собственную очередь и запускает их для обработки синхронизации в конце и т. Д.

«Трюк», который я использовал в этом случае заключается в том, чтобы не вызвать делегата непосредственно в пуле потоков, а скорее вызвать метод в моем планировщике, который обертывает делегат и обрабатывает исключение более изящно. Таким образом, вызов внутреннего метода всегда обрабатывается соответствующим образом (для меня).

Когда происходит исключение, мой планировщик уведомляется и прекращает планирование будущих задач (что является хорошим бонусом), но также заботится о том, чтобы сообщить вызывающему, что существует одно исключение.

3

Если поток завершился неудачно, вы можете отметить, что в локальной переменной функции CompleteAndQueuePayLoads произошла по меньшей мере одна ошибка и добавлена ​​переменная исключения/отказов, которая будет рассмотрена позже.

1

Вы можете изучить расширения параллельной библиотеки для 3.5. Вы можете использовать Parallel.Invoke в своем блоке кода, чтобы делать именно то, что вы пытаетесь сделать.

+0

Да, я недавно видел это, но я решил эту проблему, используя массив waithandles, с методом, который выполняет итерацию через массив, чтобы увидеть, что все они были выпущены. –

Смежные вопросы