0

アプリケーションの起動時にスレッドを起動し、BackgroundWorkerを使用せずにUIがスレッドを動作させるのを待ちます。このスレッドは、作業が与えられていないときにスリープし、UIが何かをするように要求するとウェイクアップします。

詳細:

シンプルなWPFアプリ:ファイルを長期ストレージにコピーするためのStorageClassがあります。このクラスは、WPFアプリケーションの一部です。ユーザーがボタンをクリックしてファイルを長期ストレージ(低速アレイ)に保存するときに、このファイルを高速ストレージアレイから長期ストレージにコピーするスレッドが必要です。これらは大きなファイルであり、UIをブロックしたくありません。命令の転送を待つ1つのスレッドを使用したいと思います。これにより、私がやろうとしていることがより明確になることを願っています。

4

1 に答える 1

2

.NET 4.0以降を使用している場合は、直接スレッド化するよりもTPLを使用することをお勧めしBlockingCollection<T>ます。また、UIがコレクションを介して「作業を行う」ことができる方法として、を使用することをお勧めします。

Taskコンシューマーは、 (ここでもTPLから)長時間実行される可能BlockingCollection<T>性があります。このようにして、スリープやそのような手動のアーティファクトは必要ありません。これによりBlockingCollection<T>、一定期間の待機をブロックできます。時間、そしてアイテムが消費する準備ができたら再開します。

したがって、キャンセルトークンのソース、ブロックコレクション、およびタスクを次のように定義できます。

    private BlockingCollection<Transaction> _bin = new BlockingCollection<Transaction>();
    private CancellationTokenSource _tokenSource = new CancellationTokenSource();
    private Task _consumer;

また、コンシューマーメソッドは次のように定義できます。

    private void ConsumeTransactions()
    {
        // loop until consumer marked completed, or cancellation token set
        while (!_bin.IsCompleted && !_tokenSource.Token.IsCancelRequested)
        {
            Transaction item;

            // try to take item for 100 ms, or until cancelled 
            if (_bin.TryTake(out item, 100, _tokenSource.Token)
            {
                // consume the item
            }
        }
    }

次に、フォームが読み込まれたときに、次のようにしてタスクを実行します。

// when you have a task running for life of your program, make sure you
// use TaskCreationOptions.LongRunning.  This typically sets up its own
// dedicated thread (not pooled) without having to deal with threads directly
_consumer = Task.Factory.StartNew(ConsumeTransactions, _tokenSource.Token, 
                                  TaskCreationOptions.LongRunning, TaskScheduler.Default);

次に、次の手順でアイテムを追加します。

        _bin.TryAdd(someTransaction);

Transaction実行する作業単位を定義するものはどこにありますか...

そして最後に、アプリケーションがシャットダウンしたい場合、次のことができます。

_bin.CompleteAdding();

これは、これ以上アイテムがキューに追加されないことをコンシューマーに通知します。これにより、がTryTake()返さfalseれ、ループ_bin.IsCompletedが終了しますtrue

長時間実行されているタスクは、キャンセルトークン(TPLも)がシャットダウンするように設定されるまで、ブロッキングgetをループできます...

于 2012-07-25T16:09:28.573 に答える