2

私はBlockingCollection生産者消費者パターンに を使用していますが、例外があり、特許を書いていると思います-グーグルでの結果は2つだけです! 期待は「CompleteAddingはコレクションへの追加と同時に使用できない可能性があります」であり、次のようにTryAddBlockingCollectionでiが発生した場合に発生します。

 public void EnqueueTask(T item)
    {
        if (!_cancellationTokenSource.IsCancellationRequested)
        {
            _workerQueue.Add(item);
        }
    }

これ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.
    }

マイクロソフトの誰かがアイデアを得ましたか? キャンセル後、CompleteAdding を呼び出す前にスリープ状態にする必要がありますか?

4

1 に答える 1

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");
            }

では_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");
            }

お使いのバージョンでは、変数「i」がキャプチャされ、すべてのタスクが同じ変数を使用します。i == _workers.Lengthfor ループが完了した後に実行されるため、最初のいくつかを除くすべてが表示されます。

これは、古典的なラムダ + キャプチャされた変数の問題です。

于 2010-10-14T20:19:00.863 に答える