如果我确定它不会引发异常,是否可以安全地离开任务?在收集之前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无法收集继续任务和数组中的所有任务,直到所有任务完成。