C# 使用 BlockingCollection 正确中止总是 运行 的线程

C# Correctly aborting a always running thread with a BlockingCollection

我是 运行 一个拥有

的线程
while(isRunning) 
{ 
    blockingCollection.Take()
}

首先我将 isRunning 设置为 false。然后我调用 thread.Interrupt 来阻止 blockingCollection 等待新项目。之后,我为 class 运行 catch 块中的线程调用 Dispose 方法。

这是 best/correct 的方法吗?

BlockingCollection 具有 CompleteAdding() 方法并完全支持 Cancellation。

while(isRunning && ! blockingCollection.IsCompleted) 
{ 
   isRunning = blockingCollection.TryTake(out someThing, -1, cancelToken);
}

这样你可以而且应该让线程正常结束,总是更好的选择。

根据 Henk 的回答,如果您希望拥有 Take() 的阻塞能力,但需要在它等待空列表时取消,您可以通过这种方式在循环外处理取消。

private void DoSomething(CancellationToken token)
{
    while (IsRunning)
    {
        MyObject next;
        try
        {
            next = _queue.Take(token);
        }
        catch(OperationCanceledException)
        {
            break; //Cancelled
        }

        // Do something with 'next'
    }

    // Cleanup

}

然后,当 'whatever' 发生需要您终止此循环时,即使列表为空并且它卡在 Take() 调用上阻塞,也只需在生成代币.

注意 - 为了安全起见,可能还建议捕获 Take() 也可能抛出的 ObjectDisposedException。查看文档以了解有关它的详细信息以及它可能抛出的原因。