4

特定のメソッドまたはメソッドのグループを呼び出すスレッド数をxだけにするようにスレッド プール マネージャに指示する方法はありますか?

私は、スレッド プール ワーカー スレッドをあちこちで使用するアプリケーションを持っています。ただし、ワーカー スレッドに委託するタスクの 1 つは Web サービス呼び出しであり、5 つを超える同時要求を拒否します。スレッド プールを 5 つのスレッドに制限したくありません。他の多くのことがスレッドを使用し、さらに多くのスレッドを処理できるからです。

スレッドプールを「コンパートメント化」して、「いつでもこの特定のことを実行している最大xスレッドがアクティブになりますが、残りのスレッドは他のことを行うことができます」と言う方法はありますか?

4

4 に答える 4

4

セマフォを使用して、希少なリソースへのアクセスを最大に制限します。5.

セマフォは、N スレッドの同時アクセスのみを許可するように構成できます。N=5 でセマフォを構成し、Web サービスを呼び出す前にすべてのスレッドを待機させる必要があります。

于 2012-04-19T19:59:11.843 に答える
2

別のスレッドプールと SetMaxThreads(5) を作成します - これが最も簡単な方法です。

OK、Threadpool クラスではできません。

私が反対票を投じないように:

public abstract class Task {
    public EventHandler FonComplete;
    public ThreadPool myPool;
    protected int param;
    public Exception error;
    public Task(int inParam, EventHandler OnDone) { param = inParam; FonComplete = OnDone; }
    public abstract void run();
};


public class PoolThread{
private
    BlockingCollection<Task> FinQueue;
public
    PoolThread(BlockingCollection<Task> inQueue)
    {
       FinQueue=inQueue; 
    }
    Task inMess;
    public void run(){
        while(true){
            inMess=FinQueue.Take();
            if(inMess==null) return;
            try
            {
                inMess.run();
                inMess.error = null;
            }
            catch (Exception e)
            {
                inMess.error = e;
            }
            inMess.FonComplete(inMess, null);
        }
    }
};

public class ThreadPool {
    int FthreadCount;
    BlockingCollection<Task> queue;
    void startThread(){
            PoolThread thisPoolThread=new PoolThread(queue);
            Thread thisThread=new Thread(new ThreadStart(thisPoolThread.run));
            thisThread.Priority = ThreadPriority.BelowNormal;
            thisThread.IsBackground = true;
            thisThread.Start();
    }
    void SetThreadCount(int newCount){
        while(FthreadCount<newCount){startThread();};
        while(FthreadCount>newCount){
            queue.Add(default(Task));
            FthreadCount--;
        };
    }
    public ThreadPool(int initThreads){
        queue=new BlockingCollection<Task>();
        for(FthreadCount=0;FthreadCount<initThreads;FthreadCount++) startThread();
    }
    public int threadCount{
        get{return FthreadCount;}
        set
        {
            while (FthreadCount < value) {
                startThread();
                FthreadCount++;
            };
            while (FthreadCount > value)
            {
                queue.Add(default(Task));
                FthreadCount--;
            }
        }
    }

    public void submit(Task task){
        task.myPool=this;
        queue.Add(task);
    }
};

}

「本物の」System.Threading.Threadpool とは異なりますが、固定数のスレッドを持つスレッドプールです。

于 2012-04-19T19:49:43.140 に答える
0

複数のスレッド プールを使用できます。Web サービスへのリクエスト用に最大 5 つのスレッドを持つスレッド プール A と、それ以外のすべてに対してはるかに高い最大値を持つスレッド プール B を用意します。

于 2012-04-19T19:45:48.290 に答える
0

まず、直接Task使用する代わりにクラスを使用しThreadPoolます。各作業項目をループして子タスクをスピンアップする親タスクをスピンアップします。親タスクは、セマフォを使用して、同時の子タスクの数を制限します。

これは、子タスクをセマフォで待機させるよりもはるかに優れています。これは、セマフォで待機しているプールされたスレッドが多数ではなく 1 つだけであるためです。

var parent = Task.Factory.StartNew(
  () =>
  {
    var semaphore = new SemaphoreSlim(5, 5);
    foreach (var workitem in YourWorkItems)
    {
      var capture = workitem;
      semaphore.Wait();
      Task.Factory.StartNew(
        () =>
        {
          try
          {
            CallWebService(capture);
          }
          finally
          {
            semaphore.Release();
          }
        }, TaskCreationOptions.AttachedToParent);
    }
  }, TaskCreationOptions.LongRunning);

// Optionally wait for the parent to complete here.
// Because our child tasks are attached this will wait until everything is done.
parent.Wait(); 
于 2012-04-19T20:58:24.283 に答える