对 Task.GetAwaiter().OnCompleted() 的调用是否会因为垃圾收集而失败?
Can a call to Task.GetAwaiter().OnCompleted() fail because of garbage collection?
示例:
var task = Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
throw new Exception("fault!");
});
task.GetAwaiter().OnCompleted(() =>
{
if (task.IsFaulted)
{
Console.WriteLine(task.Exception);
}
});
上面的代码使用 TaskAwaiter 等待任务完成。我在整个网络的几个示例中看到过这样的代码,使用 OnCompleted 或 GetResult.
是否有必要明确保留对等待者的引用,以便回调正常工作?换句话说,如果等待者在任务终止之前被垃圾收集,是否有问题?
Is it necessary to keep a reference to the awaiter explicitly in order for the callback to work? In other words, is it a problem if the awaiter is garbage collected before the task terminates?
我不明白怎么可能。唯一可能成为问题的方法是是否需要使用 awaiter 对象。但要尝试这样做,它必须有一个对等待者对象的引用。但是如果它引用了 awaiter 对象,则该对象不会被垃圾回收。
也就是说,您为什么要以这种方式实现延续?通常,您只需使用 await
并在 await
调用之后在同一方法中编写延续。即使在由于某种原因它不起作用的情况下(例如不在 async
方法中),您通常也会使用 ContinueWith()
方法。
你为什么打电话给 GetAwaiter()
?听起来您可能会受益于在您的问题中提供更多细节,以便可以提供满足您更广泛需求的答案(或者您可以提出第二个问题以征求相关建议)。
简而言之,在欣赏了所有答案和评论之后,我对使用 GetAwaiter()
的认识是:不要这样做。
如果您需要它,这很可能表明您的异步设计急需重构。
示例:
var task = Task.Factory.StartNew(() =>
{
Thread.Sleep(1000);
throw new Exception("fault!");
});
task.GetAwaiter().OnCompleted(() =>
{
if (task.IsFaulted)
{
Console.WriteLine(task.Exception);
}
});
上面的代码使用 TaskAwaiter 等待任务完成。我在整个网络的几个示例中看到过这样的代码,使用 OnCompleted 或 GetResult.
是否有必要明确保留对等待者的引用,以便回调正常工作?换句话说,如果等待者在任务终止之前被垃圾收集,是否有问题?
Is it necessary to keep a reference to the awaiter explicitly in order for the callback to work? In other words, is it a problem if the awaiter is garbage collected before the task terminates?
我不明白怎么可能。唯一可能成为问题的方法是是否需要使用 awaiter 对象。但要尝试这样做,它必须有一个对等待者对象的引用。但是如果它引用了 awaiter 对象,则该对象不会被垃圾回收。
也就是说,您为什么要以这种方式实现延续?通常,您只需使用 await
并在 await
调用之后在同一方法中编写延续。即使在由于某种原因它不起作用的情况下(例如不在 async
方法中),您通常也会使用 ContinueWith()
方法。
你为什么打电话给 GetAwaiter()
?听起来您可能会受益于在您的问题中提供更多细节,以便可以提供满足您更广泛需求的答案(或者您可以提出第二个问题以征求相关建议)。
简而言之,在欣赏了所有答案和评论之后,我对使用 GetAwaiter()
的认识是:不要这样做。
如果您需要它,这很可能表明您的异步设计急需重构。