0

backgroundworkerネットワーク経由で接続するプロセスを実行するために複数を使用しています。の行数に基づいて、datagridview各行の値をフェッチし、長いプロセスを実行する別のクラス メソッドを通過します。ここでは for ループを使用してバックグラウンド ワーカーを開始しているため、問題はプロセスの開始時であり、行数に基づいてdatagridviewより多くのバックグラウンド ワーカーが実行を開始します。しかし、私はこれを制限したい。たとえば、50 行ある場合、一度に 5 つのバックグラウンド ワーカーを実行したいだけです。それらの 5 つがタスクを終了したら、次の 5 つを開始する必要があります。では、それらを制限する方法は?

次のコードを使用しました:

Backgroundworker bs;
private void button1_Click(object sender, EventArgs e)
{
  threadNumber = 0;
  threadRunning = 0;
  for(int i=0;i<datagridview1.Rows.Count;i++)
    {
       bs = new Backgroundworker();
       bs.DoWork += new DoWorkEventHandler(bs_DoWork);
       bs.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bs_Completed);
       bs.WorkerSupportCancellation = true;
       bs.RunWorkerAsync(i);
    } 
}

private void bs_DoWork(object sender, DoWorkEventArgs e)
  {
    int i = (int)e.Argument;
    while(bs.CancellationPending !=true && threadNumber < datagridview1.Rows.Count)
     {
      lock (this)
        {
            for (int i = 0; i < Max_Threads - threadRunning; i++)
            {
                if (threadNumber < datagridview1.Rows.Count)
                {
                   Webmethod obj = new webmethod();
                   obj.Callmethod(i); // this takes long time to perform
                   threadNumber +=1;
                   threadRunning +=1;
                 }
              }
          }
 }
 }

しかし、プロセスを開始すると、すべてのバックグラウンドワーカーがタスクを開始します。誰でもこれで私を助けることができますか?

前もって感謝します..

4

1 に答える 1

2

あなたがやろうとしていることは完全には明らかではありません。クリック メソッドはBackgroundWorkerデータ行ごとに新しいものを開始しますが、DoWorkハンドラーは行ごとに内部ループも実行します。非常に紛らわしいです。あなたが望むのは、ワーカーを開始し、行の処理に協力させることだと思います。Max_Threads

のインクリメントに問題がありますthreadNumber。インクリメントはアトミック操作ではないため、同時にインクリメントする 2 つのスレッドが相互に影響を与える可能性があります。おそらくInterlocked.Incrementを使用して、アクセスを同期する必要があります。

あなたがやりたいことはこれだと思います:

int threadNumber;
private void button1_Click(object sender, EventArgs e)
{
    threadNumber = -1;
    // Start Max_Threads workers
    for(int i=0; i<Max_Threads; i++)
    {
        var bs = new Backgroundworker();
        bs.DoWork += new DoWorkEventHandler(bs_DoWork);
        bs.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bs_Completed);
        bs.WorkerSupportCancellation = true;
        bs.RunWorkerAsync();
    } 
}

private void bs_DoWork(object sender, DoWorkEventArgs e)
{
    // Process items until cancellation requested, or until end of list
    while(!bs.CancellationPending)
    {
        int rowNumber = Interlocked.Increment(ref threadNumber);
        if (rowNumber >= datagridview1.Rows.Count)
        {
             break;
        }
        Webmethod obj = new webmethod();
        obj.Callmethod(rowNumber); // this takes long time to perform
    }
}
于 2013-10-14T15:45:50.107 に答える