1

私は .NET 4.0 ASP.NET プロジェクトを持っています。これには、これまで本当にいじったことのないスレッド作業が必要であり、これを何日も見てきましたが、まだ無知です =/

基本的には、デリでチケットを取り、順番を待ってから戻ってくるようなものを望んでいます。これを関連付けてみて、意味があるかどうかを確認します...

関数が開始 ---> 「チケットを取得」する必要があるセクションに移動し (blockingcollection 内の何らかのタイプのアイテムをキューに入れると仮定します)、他の「チケット」(同じ関数の他のインスタンス) が完了するまで待機します。関数に再開の OK を与えます (ブロック コレクションはキュー内のアイテムに到達します) ---> 関数を終了します。

キューで作業する必要はありません/したくないのですが、関数の他のインスタンス間で順番が変わるのを関数に静的に待機させたいだけです。それは理にかなっていますか?それは可能ですか?

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

4

2 に答える 2

1

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

ただし、実際にお勧めするのは、SemaphoreSlimクラスを使用して、この脆弱なWebサービスへの同時リクエストの数を調整することです。おそらく、許容される同時実行量として、1から5程度の数値を選択する必要があります。

于 2012-04-13T15:44:57.530 に答える
0

ドキュメントごとにドキュメントを調査し、コードを何度も書き直して遊んだ後、AutoResetEvent の権利を使用していないことと、専用スレッドでブロッキング コレクションを使用する方法を最終的に理解しました。したがって、BlockingCollection で AutoResetEvent を使用する最終的な解決策は次のとおりです。以下のこのソリューションでは、100% の場合は同じ結果が得られない可能性があります (ブロッキング コレクションに何かが入力されたときのスレッドのタイミングに関係していると思われるためです) が、最終的な結果は、まさに私が望んでいることです。

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);
    }
}
于 2012-04-17T04:39:58.513 に答える