如果我確定它不會引發異常,是否可以安全地離開任務?在收集之前GC會等到任務完成嗎?是否安全左任務unreferenced
這裏是我的方法的一個例子,它將任務數組轉換爲完成所有任務完成時完成(取消或失敗)的任務。我的應用程序因任務未被查看的異常而失敗(通過在任何我使用任務的地方記錄Task.Id,我發現任何未被觀察到的任務是提供給此方法的任務或至少具有相同的ID)。我不知道爲什麼會發生這種情況,除了垃圾回收器收集從Task.Factory.ContinueWhenAll返回的任務時,不會等待完成,因爲它也可能會從數組中收集所有未完成的任務,並且如果至少有一個失敗的任務它會導致任務未被察覺的例外。聽起來很瘋狂,但我沒有看到對他所發生的事情的另一種解釋。那有可能嗎?
public static Task ToWhenAllTask(this Task[] tasks, bool cancelIfAnyCanceled = true)
{
if (tasks != null && tasks.Length == 0)
throw new ArgumentException();
var tcs = new TaskCompletionSource<object>();
Task.Factory.ContinueWhenAll(tasks, ts => {
try
{
List<Exception> errors = null;
bool canceled = false;
foreach (Task task in ts)
{
AggregateException ex = task.Exception;
if (ex != null)
{
if (errors == null)
errors = new List<Exception>();
errors.Add(ex.Flatten());
}
if (task.IsCanceled)
canceled = true;
}
if (errors != null)
tcs.TrySetException(errors);
else if (cancelIfAnyCanceled && canceled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(null);
}
catch(Exception ex)
{
// there is nothing to fail in this method but just in case
tcs.TrySetException(ex);
}
}, TaskContinuationOptions.ExecuteSynchronously);
return tcs.Task;
}
PS。說實話,我認爲,直到任務完成TaskScheduller持有對它的引用(在我的情況下,繼續任務也持有對任務數組的引用)。所以GC無法收集繼續任務和數組中的所有任務,直到所有任務完成。