Как отлавливать ошибки из рабочих потоков в консольном приложении, написанном на C # - PullRequest
2 голосов
/ 16 марта 2011

В настоящее время у меня есть небольшое консольное приложение, которое выполняет несколько задач (используя Parallel.ForEach ), и каждая из этих задач создает подпотоки, используя ThreadPool.QueueUserWorkItem .

Я бы хотел, чтобы приложение обрабатывало любые исключения, выдаваемые этими задачами / потоками.

Сработает ли окружение оператора Parallel.ForEach с try..catch , если потоки выдают какие-либо ошибки или они просто исчезнут?

РЕДАКТИРОВАТЬ: Эти подпотоки имитируют пользователей системы. См. этот вопрос.

Ответы [ 5 ]

4 голосов
/ 16 марта 2011

Окружение заявления не сделает работу. Вы можете сделать что-то вроде этого:

public static void Main(string[] args)
{             
    string[] files = System.IO.Directory.GetFiles(@".", "*.*");      

    Parallel.ForEach(files, x =>
    {
      try
      {
        MyAction(x);
      }
      catch(Exception ex)
      {
        Console.WriteLine(ex.ToString());
      }
    });        
}

static void MyAction(string x)
{      
  throw new ApplicationException("Testing: " + x);
}
2 голосов
/ 16 марта 2011

Не используйте QUWI.У меня есть краткое сравнение типов фоновых задач в моем блоге (Task, BackgroundWorker, Delegate.BeginInvoke, ThreadPool.QueueUserWorkItem и Thread).

Для фоновых задачTask явный победитель.QueueUserWorkItem очень низкоуровневый по сравнению.

В частности, ваша проблема - распространение ошибок, и Task имеет встроенную поддержку для этого, которой полностью не хватает в QueueUserWorkItem.Вы можете создать его в себе, заключив свой делегат в try / catch, сохранив исключение как часть аргумента делегата (или как связанную переменную лямбда-выражения), явно проверив егопозже, и сделаем некоторое технически неподдерживаемое отражение , чтобы сохранить след стека.

Но зачем?Task поддерживает распространение ошибок из коробки.

1 голос
/ 16 марта 2011

вы можете обработать все исключения с помощью try / catch, например:

try
{
    MyParallelMethod();
}
catch(Exception e)
{
    //...
}

и в вашем методе сделайте что-то подобное:

public void MyParallelMethod()
{
    var data = new List<String>(); 
    //...

    Parallel.ForEach(data, d =>
    {
        try
        {
            //...
        }

        catch (Exception e) 
        { 
            //...    
        }
    });
 }
0 голосов
/ 16 марта 2011

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

Parallel.ForEach не будет обрабатывать его для вас, поскольку исключение будет вызвано не в потоке, который вызывает Parallel.ForEach.

Альтернативой является использование Task<T>.

0 голосов
/ 16 марта 2011

Будет ли окружение оператора Parallel.ForEach с try..catch работать, если потоки выдают какие-либо ошибки, или они просто вымрут?

Нет, вам нужно поставить try / catchвнутри суб темы.

...