2012-04-15 7 views
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回発射する場合はロックが解除されるまで、すべてのスレッドがロックを待機します。私は最後のスレッドを実行することを確認したい。スレッドがロックの所有者であることを待っているときに、ロックを所有している次のスレッドをどのように決定することができますか。私は彼らが私がスレッドを作成したために、リソースを所有したい...

EDIT

私は.NET 4.0でこのアプリケーションを作成しておりません。私が達成しようとしていたことを言及してくれなかったのは残念です。私は多くのデータをフィルタリングしているオートコンプリートコントロールを作成しています。メインウィンドウをフリーズする必要はありません。私は結果をフィルタリングしたいと思っています。また、ユーザーの入力時に結果をフィルタリングする必要があります。ユーザーが5文字を一度に入力すると、すべてのスレッドを停止したいので、最後のスレッドに興味があります。ロックはすべてのスレッドをブロックするため、作成した最後のスレッドが最初にロックを所有することがあります。

+0

私は周りにそれを設計しようと思います* 1 *「自体を放棄する」「流れを変える」か、できることをサポートスレッド(またはBackgroundWorkerの)...複数のスレッドは毛むくじゃくし、後のものが来たら前のクエリに取り組む必要はありません。 –

答えて

4

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

タスクをキャンセルするだけの場合:here is a SO question on how to cancel TPL tasks.最後のものを除くすべてをダンプする場合は、なぜリソースを無駄にするのですか。

4.0を使用していない場合は、同じことをBackground Workerで実行できます。同じことを達成するための定型コードがもっと必要になります:)

+0

私は実際にユーザー型データとしてデータをフィルタリングしています。メインスレッドがフリーズしないようにするため、別のスレッドで実行しました。ユーザーがそのメソッドを5回呼び出すと、私は最後のものだけに興味がありますが、ロックのために最後の例があると、プログラムはそれぞれが完了して1つずつ実行するのを待たなければなりません。 –

+0

@TonoNam TPLを使用することはできますが、新しいクリックごとに現在のタスクをキャンセルするだけです。私はキャンセルを含むように私の答えを更新しました –

+0

@トノナム4.0を使用しないことに関するあなたの更新を見ました。私は同じアイデアを達成するためにBackgroundWorkerを使用することを提案するために私の答えを更新しました –

0

私はJustinが.NET 4 Task Parallel Libraryを使うべきであるという点で同意します。しかし、完全な制御が必要な場合は、デフォルトのタスクスケジューラ(LIFOを優先)を使用するのではなく、独自のタスクスケジューラ(http://msdn.microsoft.com/en-us/library/system.threading.tasks.taskscheduler.aspx)を作成して、優先するタスクを決定するロジックを実装してください。

スレッドを直接使用することは、.NETスレッディングに関する深い知識がない限りお勧めしません。 .NET 4.0を使用している場合は、タスクとTPLが優先されます。

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); 
} 
関連する問題