2015-08-10 2 views
7

Некоторые из нас предпочитают кодировать в стиле исключения-света. Однако, если вы ждете задачи параллельной библиотеки задачи, и задача забросила исключение, она также вызовет исключение в вызывающем потоке. Существует ли (желательно стандартный) способ избежать такого поведения и просто проверить ответ на исключения, когда вы его вернете?Есть ли способ подождать задания TPL без исключения?

+0

Таким образом, в основном вы спрашиваете, вызвал ли какой-то код исключение, есть ли способ обнаружить его, не поймав его? –

+0

Вы абсолютно уверены, что вам нужно * подождать * для задания? Я бы порекомендовал вам '.ContinueWith (...)' все, что вы сделали после вызова Wait. –

+1

Это экземпляр, в котором вы должны использовать продолжения для опроса статуса предшествующей задачи. Продолжение является основополагающим для TPL. Избегайте взломать их. Более того, проглатывание исключений - запах кода. – Gusdor

ответ

7

Вы можете использовать Task.WaitAny как:

 var task = Task.Run(() => 
     { 
      // ... 
      throw new Exception("Blah"); 
     }); 
     Task.WaitAny(task); 
     if (task.IsFaulted) 
     { 
      var error = task.Exception; 
      // ... 
     } 
     else if (task.IsCanceled) 
     { 
      // ... 
     } 
     else 
     { 
      // Success 
     } 
2

Основываясь на том, что вы написали, можете ли вы поймать исключение и проверить свойство IsFaulted? IsFaulted

+0

Я пошел с Task.WaitAny подхода. Чтобы дать вам контекст для почему, вызываемый код - это код библиотеки, который я не мог изменить и вызывался из-за пределов TPL, но исключения были довольно распространены и, хотя их нужно было обрабатывать, было ужасно много шума для если вы ударили «break on exception» on, который я делаю все время. –

1

Поймать исключение в пределах Задачи и вернуть его в результате?

var task1 = Task.Factory.StartNew(() => 
{ 
    try 
    { 
     throw new MyCustomException("I'm bad, but not too bad!"); 
    } 
    catch(Exception ex) 
    { 
     return new Result { Error = ex }; 
    } 
}); 
3

К сожалению, эта функциональность не встроена. Используйте это решение:

myTask.ContinueWith(_ => { }, TaskCOntonuationOptions.ExecuteSynchronously).Wait(); 

Вы можете сделать это способом расширения.

+1

Можете ли вы объяснить, почему это решение решает проблему? – Gusdor

+1

@ Гусдор, что ты имеешь в виду? он делает именно то, что хочет OP. Ожидание задания без исключения. – boot4life

4

Вы не можете ждать на поврежденную задаче, не поднимая исключение. Но вы можете ждать продолжение к этой задаче, которая будет завершить только после того, как исходная задача завершена, не поднимая исключение:

public static Task SwallowExceptions(this Task task) 
{ 
    return task.ContinueWith(_ => { }); 
} 

faultedTask.SwallowExceptions().Wait(); 
if (faultedTask.IsFaulted) 
{ 
    // handle exception 
} 

Если ваша задача возвращает значение, вы можете представлять, что в методе расширений и возврат фактическое значение, если не было никаких исключений или значения по умолчанию, если они были:

public static Task<T> SwallowExceptions<T>(this Task<T> task) 
{ 
    return task.ContinueWith(completedTask => 
     completedTask.IsFaulted 
      ? default(T) 
      : completedTask.Result); 
} 
Смежные вопросы