.net 4.0上BlockingCollection的一个非常独特的例外

use*_*631 2 .net c# producer-consumer c#-4.0

我正在使用BlockingCollection生产者消费者模式,我有一个例外,我想写一个专利 - 只有谷歌的两个结果!预期是"CompleteAdding可能不会与添加到集合中同时使用",并且当我TryAdd在BlockingCollection上时会发生以下情况:

 public void EnqueueTask(T item)
    {
        if (!_cancellationTokenSource.IsCancellationRequested)
        {
            _workerQueue.Add(item);
        }
    }
Run Code Online (Sandbox Code Playgroud)

CompleteAdding处理Consumer-Producer包装类时调用它:

  public void Dispose()
    {
        if (!_IsActive)
            return;
        _IsActive = false;
        _cancellationTokenSource.Cancel();
        _workerQueue.CompleteAdding();
        // Wait for the consumer's thread to finish.
        for (int i = 0; i < _workers.Length; ++i)
        {
            Task t1 = Task.Factory.StartNew(() =>
            {
                try
                {
                    if (!_workers[i].Join(4000))
                        LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose");
                }
                catch (Exception ex)
                {
                    OnLogged(ex.Message + ex.StackTrace);
                }
            });

        }


        // Release any OS resources.
    }
Run Code Online (Sandbox Code Playgroud)

微软的任何人都有想法?我应该在取消之后和调用CompleteAdding之前睡觉吗?

Hen*_*man 5

看看这段代码:

    for (int i = 0; i < _workers.Length; ++i)
    {
        Task t1 = Task.Factory.StartNew(() =>
        {
            try
            {
                if (!_workers[i].Join(4000))   << == Here
                    LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose");
            }
Run Code Online (Sandbox Code Playgroud)

_workers[i].Join(4000),价值i不是你想象的那样.再试一次:

   for (int i = 0; i < _workers.Length; ++i)
    {
        int j = i;  // copy
        Task t1 = Task.Factory.StartNew(() =>
        {
            try
            {
                if (!_workers[j].Join(4000))  // j
                    LogWriter.Trace("Failed to join thread", "ThreadFailureOnDispose");
            }
Run Code Online (Sandbox Code Playgroud)

在您的版本中,捕获变量"i"并且所有任务使用相同的var.除了前几个之外的所有部分都会看到i == _workers.Length因为它们在for循环完成后执行.

这是一个经典的lambda +捕获var问题.

  • 啊,经典捕获的迭代变量.好点. (2认同)