使用CancellationToken的正确方法是什么?

时间:2018-08-27 17:23:54

标签: cancellationtokensource

我创建了一个服务器,该服务器执行带有阻塞操作的某些任务,我已经使用了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等待任务完成。这样我就可以安全清理所有对象。

0 个答案:

没有答案