2015-10-30 4 views
2

Это последующая деятельность после this question. Я также прочитал статью "Tasks and Unhandled Exceptions" Стивена Туба, и я думаю, что я понимаю, как работают задачи и исключения и что означает «наблюдаемая задача». Я, однако, не могу понять, как сказать, наблюдался ли Task или нет. Возможно ли это вообще без использования отражения?Как узнать, была ли «Наблюдаемая задача»?

Я хотел бы позаимствовать @Noseratio's code в качестве примера:

static async void Observe(Task task) 
{   
    await task; 
} 

// ... 

var taskObserved = false; 
var task = DoSomething() 
try 
{ 
    bool ready = await DoSomethingElse(); 
    if (!ready) 
     return null; 

    var value = await DoThirdThing(); // depends on DoSomethingElse 
    taskObserved = true; 
    return value + await task; 
} 
finally 
{ 
    if (!taskObserved) 
     Observe(task); 
} 

Если бы мы могли сказать, был ли соблюден задача, это можно было бы сделать проще и более удобным для чтения:

static async void Observe(Task task) 
{   
    if (!task.WasObserved) 
     await task; 
} 

// ... 

var task = DoSomething() 
try 
{ 
    bool ready = await DoSomethingElse(); 
    if (!ready) 
     return null; 

    var value = await DoThirdThing(); // depends on DoSomethingElse 
    return value + await task; 
} 
finally 
{ 
    Observe(task); 
} 

ответ

5

задачи не знаю, ожидаются ли они или нет. Это вроде как спрашивать, знает ли целое число, добавлено ли оно в другое целое число или нет.

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

Вы действительно не должны писать код, зависящий от ожидаемой задачи. Если семантика DoSomething является то, что она всегда должна ожидаться, даже если результат игнорируется (очень странное - но технически правильное - требование), то этот код должен быть достаточным:

var task = DoSomething(); 
try 
{ 
    bool ready = await DoSomethingElse(); 
    if (!ready) 
    return null; 

    var value = await DoThirdThing(); // depends on DoSomethingElse 
    return value + await task; 
} 
finally 
{ 
    await task; 
} 

С другой стороны, если семантика DoSomething в том, что задача может быть проигнорирована, если результат не нужен после того, как все (что гораздо более вероятно, так), то этот код должен быть достаточным:

var task = DoSomething(); 
bool ready = await DoSomethingElse(); 
if (!ready) 
    return null; 

var value = await DoThirdThing(); // depends on DoSomethingElse 
return value + await task; 

нет необходимости возиться с волнуясь о ожидалось ли задание.

+0

Спасибо, Стивен, я надеялся, что вы ответите. На самом деле меня интересует «наблюдаемый» (а не «ожидаемый») статус. Например, если «Task.Exception» был затронут и т. Д. У меня есть вопрос о вашем 1-м фрагменте кода, но не собирается ли это же исключение 2 раза? Итак, я собираюсь освободить фрейм стека за 1-й бросок? – avo

+1

@avo: Если 'task' завершается в неисправном состоянии, вы не потеряете фрейм стека. Стек уже захвачен и помещен в объект 'Exception' в' task.Exception'. 'await' достаточно умен, чтобы сохранить захваченный стек одновременно. –

+0

В идеале я бы хотел, чтобы все еще можно было распространять исключения из «DoSomethingElse» или «DoThirdThing», если любой из них выбрасывает «DoSomething». Однако «DoSomething» берет на себя эти исключения в этом случае. – avo

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