4

2 つのスレッドが同じリソースにアクセスするのを避けて、別のスレッドで実行したい関数があります。また、スレッドが現在実行されている場合は、そのスレッドを停止して新しいスレッドの実行を開始することを確認したいと思います。これは私が持っているものです:

volatile int threadCount = 0; // use it to know the number of threads being executed
private void DoWork(string text, Action OncallbackDone)
{
    threadCount++;
    var t = new Thread(new ThreadStart(() =>
    {
        lock (_lock) // make sure that this code is only accessed by one thread
        {
            if (threadCount > 1) // if a new thread got in here return and let the last one execute
            {
                threadCount--;
                return;
            }
            // do some work in here
            Thread.Sleep(1000);
            OncallbackDone();
            threadCount--;
        }
    }));
    t.Start();
}

そのメソッドを 5 回起動すると、ロックが解放されるまですべてのスレッドがロックを待機します。ただし、最後のスレッドを確実に実行したいと思います。スレッドがロックの所有者になるのを待っているときに、ロックを所有する次のスレッドを特定するにはどうすればよいですか。スレッドを作成した順序でリソースを所有してもらいたい...

編集

私はこのアプリケーションを .net 4.0 で作成していません。私が達成しようとしていたことに言及していないことをお詫びします。大量のデータをフィルタリングするオートコンプリート コントロールを作成しています。結果をフィルタリングするたびにメイン ウィンドウをフリーズさせたくありません。また、ユーザーの種類に応じて結果をフィルタリングしたいと考えています。ユーザーが一度に 5 文字を入力すると、すべてのスレッドを停止したいので、最後のスレッドだけに関心があります。ロックはすべてのスレッドをブロックするため、作成した最後のスレッドが最初にロックを所有する場合があります。

4

3 に答える 3

4

あなたはこれを過度に複雑にしていると思います。4.0 を使用できる場合は、Task Parallel Libraryを使用してください。これを使用すると、 ContinueWith関数を設定して、特定の順序で発生する必要があるスレッドが指定した順序で実行されるようにすることができます。これがあなたが探しているものではない場合、実際にはスレッドを使用しないことをお勧めします。これは、並列処理を強制しようとしている同期アクションのように聞こえるからです。

タスクをキャンセルするだけの場合: TPL タスクをキャンセルする方法に関する SO の質問があります。最後の1つを除いてすべてをダンプするだけなら、なぜリソースを無駄にするのでしょうか。

4.0 を使用していない場合は、バックグラウンド ワーカーを使用して同じことを行うことができます。同じことを達成するには、より多くの定型コードが必要です:)

于 2012-04-15T03:15:05.900 に答える
0

これはあなたたちが投稿したリンクを読んだ後に私が思いついたものです。私はキューが必要だったと思うので、実装しました:

volatile int threadCount = 0;
private void GetPredicateAsync(string text, Action<object> DoneCallback)
{          
    threadCount++;
    ThreadPool.QueueUserWorkItem((x) =>
    {                
        lock (_lock)
        {
            if (threadCount > 1) // disable executing threads at same time
            {
                threadCount--;
                return; // if a new thread is created exit. 
                        // let the newer task do work!
            }
            // do work in here

            Application.Current.Dispatcher.BeginInvoke(new Action(() =>
            {
                threadCount--;                        
                DoneCallback(Foo);
            }));

        }
    },text);
}
于 2012-04-15T14:54:15.323 に答える