我创建了一个服务器,该服务器执行带有阻塞操作的某些任务,我已经使用了cancelToken来阻止带有阻塞操作的那些任务。以下是TcpConnection的示例任务:
private List<CancellationTokenSource> cancellations = new List<CancellationTokenSource>();
:
:
private async Task ListenAsync()
{
try {
CancellationTokenSource cancellation = new CancellationTokenSource();
cancellations.Add(cancellation);
TcpClient client = await Task.Run(
() => listener.AcceptTcpClientAsync(),
cancellation.Token);
:
:
}
}
当我需要停止服务器时,我将尝试取消列表中的所有取消令牌,然后销毁所有任务。
foreach (CancellationTokenSource cancellation in cancellations)
{
cancellation.Cancel();
}
Task.WhenAll(tasks).Wait(); // wait for task complete
: (desotry objects here)
:
不幸的是,Task.WhenAll(tasks).Wait()从未返回。看来任务无法停止。但是,如果我在“任务”的“尝试捕获”中添加一些调试代码,并注释掉Task.WhenAll(任务).Wait(),它将在cancel.Cancel()之后触发catch语句,任务将完成。
似乎,如果在相同的cancel.Cancel()线程中触发了Wait(),即使我在Cancel之后添加了Thread.sleep(),也无法将控件释放到Task。我需要在其他进程中检查Task.wait()(例如,添加一个要在取消后数毫秒内触发的计时器。)或者如果我不等待任务取消,则重置任务列表(例如,tasks = new List(); )。那些正在运行的任务将到达catch块并完成,但是我不知道在任务完成之前删除了所有对那些任务的引用之后,这些资源是否可以重用。
我想知道是否有任何直接的方法可以使用CancellationToken等待任务完成。这样我就可以安全清理所有对象。