【发布时间】:2017-06-26 12:41:45
【问题描述】:
通读answers to this question 促使我思考当等待的任务抛出时会发生什么异常。所有“客户”都可以观察到异常吗?我承认我可能在这里混淆了几件事;这就是我要求澄清的原因。
我将展示一个具体的场景...假设我有一个服务器,其中包含由客户端启动的长期运行的Task 实例的全局集合。在开始一项或多项任务后,客户端可以查询他们的进度并在结果可用时检索结果,以及可能发生的任何错误。
任务本身可能执行非常不同的业务特定的事情 - 通常,没有两个是完全相同的。但是,如果其中一个客户端确实尝试启动与另一个客户端先前启动的相同的任务,则服务器应识别这一点并将第二个客户端“附加”到现有任务,而不是假脱机一个新副本。
现在,每当任何客户端查询它感兴趣的任务的状态时,它都会执行以下操作:
var timeout = Task.Delay(numberOfSecondsUntilClientsPatienceRunsOut);
try
{
var result = await Task.WhenAny(timeout, task);
if (result == timeout)
{
// SNIP: No result is available yet. Just report the progress so far.
}
// SNIP: Report the result.
}
catch (Exception e)
{
// SNIP: Report the error.
}
简而言之,它给了任务一些合理的时间来先完成它正在做的事情,然后再返回报告正在进行的进度。这意味着有一个潜在的重要时间窗口,多个客户端可能会观察到相同的任务失败。
我的问题是:如果任务恰好在此窗口期间抛出,是否所有客户端都观察到(并处理)了异常?
【问题讨论】:
-
"返回的任务将在任何提供的任务完成后完成。返回的任务将始终以
RanToCompletion状态结束,其Result设置为要完成的第一个任务。这是即使第一个要完成的任务以 Canceled 或 Faulted 状态结束,也是如此。"如果task出错,并且已完成,并且多个客户端正在通过此构造等待它,那么所有客户端都将看到出错的任务。如果他们试图检查task(不是result)的结果,他们都会得到一个异常。这不是“先到先得”的交易。 -
为了进一步简化这一点:如果您连续多次等待
Task.Run(() => throw new Exception(DateTime.Now.Ticks.ToString()))(使用异常处理程序),您每次都会收到一个带有相同时间戳的异常(以证明任务没有执行多次)。一个出错的任务可以产生任意数量的异常。 -
有趣的问题,但很容易测试自己。
-
@JeroenMostert:谢谢。请将此作为答案发布,以便我接受!
标签: c# asynchronous task