如何判断任务是否已 "observed"?

How to tell if Task has been "observed"?

这是 . I've also read Stephen Toub's "Tasks and Unhandled Exceptions" 的后续,我想我了解任务和异常的工作原理以及 "observed task" 的含义。 但是我不知道如何判断 Task 是否被观察到。 如果不使用反射,这是否可能?

我想借用作为例子:

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);
}

任务不知道它们是否已被等待。这有点像询问一个整数是否知道它是否被添加到另一个整数。

但是task的exception是可以观察到的,而是否观察到异常其实是task记住的。区分 未观察到的异常 未等待的任务 很重要。运行时对于未观察到的任务异常有一些特殊的逻辑,但不会对未等待的任务做任何特殊的事情。

您真的不应该编写依赖于任务是否已等待的代码。如果 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;

无需为是否等待任务而烦恼。