2012-04-13 13 views
1

私は.NET 4.0のASP.NETプロジェクトをいくつかのスレッド作業が必要です。以前は本当に混乱したことはありませんでした。これを数日間見てきましたが、スタティックFIFOキューとタイマーc#

基本的には、デリでチケットを買って、あなたのところに戻る前にあなたの番を待っているようなものが欲しいです。私は試してこれを関連させ、それが意味をなさないかどうかを見てみましょう...

関数が起動します---> "チケットを取る"必要なセクションに到達します(私はキューにいくつかのタイプのブロックを入れると仮定します) )、他の "チケット"(同じ関数の別のインスタンス)が完了するまで待ってから、機能を再開するまで待ちます(ブロッキングコレクションはキュー内の項目になります)。

キュー内で作業する必要はありません。機能の他のインスタンスの中で静的に待つだけです。それは理にかなっていますか?それは可能ですか?

私はたくさんの例を見てきましたが、それらのどれも意味がない/私がしたいことをしないので、可能であればコードを提供してください。

+0

特定のスレッドがデキューされているためにキューに入れられました。おそらく、AutoResetEvent.WaitOneの周りの何か? – ElementZero

答えて

0

文書の後で文書を検索してコードを書き直した後、私は最終的にAutoResetEvent権限を使用していなかったことと、専用スレッドでブロックコレクションを使用する方法を理解しました。そこで、BlockingCollectionでAutoResetEventを使用する最終的なソリューションがありました。以下のこのソリューションは、100%の時間で同じ結果を表示しない場合があります(ブロッキングコレクションに何かが入力されたときのスレッドタイミングと関係していると思うからです)。私はそれだけでアイテムたらプロデューサークラスに戻りますように使用する方法が表示されていないが、いくつかは、より多くの私は間違いなく、BlockingCollectionは最高のアイデアのように思えると思います読んだ後のでよし

class Program 
{ 
    static void Main(string[] args) 
    { 
     TaskProcessor tp = new TaskProcessor(); 

     Thread t1 = new Thread(new ParameterizedThreadStart(tp.SubmitRequest)); 
     t1.Start(1); 

     Thread t2 = new Thread(new ParameterizedThreadStart(tp.SubmitRequest)); 
     t2.Start(2); 

     Thread t3 = new Thread(new ParameterizedThreadStart(tp.SubmitRequest)); 
     t3.Start(3);   
    } 
} 

class TaskProcessor 
{ 
    private AutoResetEvent _Ticket; 

    public TaskProcessor() 
    { 
     _Continue = new AutoResetEvent(false); 
    } 

    public void SubmitRequest(object i) 
    { 
     TicketingQueue dt = new TicketingQueue(); 

     Console.WriteLine("Grab ticket for customer {0}", (int)i); 

     dt.GrabTicket(_Ticket); 

     _Continue.WaitOne(); 

     Console.WriteLine("Customer {0}'s turn", (int)i); 
    } 
} 

public class TicketingQueue 
{ 
    private static BlockingCollection<AutoResetEvent> tickets = new BlockingCollection<AutoResetEvent>(); 

    static TicketingQueue() 
    { 
     var thread = new Thread(
     () => 
      { 
       while (true) 
       {      
        AutoResetEvent e = tickets.Take(); 
        e.Set(); 
        Thread.Sleep(1000); 
       } 
      }); 
     thread.Start(); 
    } 

    public void GrabTicket(AutoResetEvent e) 
    { 
     tickets.Add(e); 
    } 
} 
1

タイマソリューションを使用したい場合は、すべての操作をBlockingCollectionにエンキューし、専用のスレッドでデキューします。このスレッドは5秒待ってからデキューされたアイテムをスレッドプールにプッシュします。この専用スレッドは、無限ループでこれを行う必要があります。デキュー、待って、プッシュ。

しかし、私が実際にお勧めするのは、SemaphoreSlimクラスを使用して、この脆弱なWebサービスに対する同時リクエストの数を制限することです。おそらく、許容される並行性の量として1から5程度の数字を選ぶべきでしょう。

+0

ええ、ここでは専用スレッドでブロッキングソリューションを使用していました。 http://stackoverflow.com/questions/9811365/conditionally-run-the-methods-of-a-class-on-a-separate-thread but私はそれを同期的に行う方法をしなかった – ElementZero

+2

私は理解しています。 IOの発行者がIOの完了を待つようにします。これを行うには、IO要求と一緒にエンキューするManualResetEventSlimを作成します。 IOが完了したら(スレッドプール上で)、このイベントを設定する必要があります。 IOの元の発行者は、そのイベントの.Wait()を実行できます。この通信はすべてパフォーマンスコストで行われますが、1桁あたりの1桁の要求については何も問題はありません。 – usr