yasmuru
yasmuru

Reputation: 1186

Limiting Number of Backgroundworkers to execute

I'm using multiple backgroundworker to execute process of connecting through network . Based on the number of rows in datagridview , it fetches each row values and passes through the another class method which perform long process. Here i'm using for loop to start the backgroundworker, so the problem is when the process starts, based on the count of datagridview rows more backgroundworkers starts to run. But i want to limit this . For example , if i have 50 rows , i just wants to execute 5 backgroundworkers at a time. After those 5 finishes the task the next 5 has to start . So how to limit those ?

I have used following code :

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;
                 }
              }
          }
 }
 }

But when i start the process, at the time all the backgroundworkers starts the task . Can anyone help me in this ?

Thanks in advance..

Upvotes: 0

Views: 560

Answers (1)

Jim Mischel
Jim Mischel

Reputation: 134015

What you're trying to do isn't entirely clear. Your click method starts a new BackgroundWorker for each data row, but then your DoWork handler also executes the inner loop for each row. Very confusing. I think what you want is to start Max_Threads workers, and have them cooperate in processing the rows.

You have a problem with incrementing your threadNumber. Increment is not an atomic operation, so it's possible that two threads incrementing it concurrently will end up stepping on each other. You need to synchronize access to that, probably by using Interlocked.Increment.

I think what you want to do is this:

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
    }
}

Upvotes: 2

Related Questions