【问题标题】:Limiting Number of Backgroundworkers to execute限制要执行的后台工作程序的数量
【发布时间】:2013-10-14 06:23:06
【问题描述】:

我正在使用多个backgroundworker 来执行通过网络连接的过程。根据datagridview 中的行数,它获取每一行的值并通过另一个执行长过程的类方法。这里我使用for循环来启动backgroundworker,所以问题是当进程开始时,基于datagridview rows的计数,更多的backgroundworkers开始运行。但我想限制这一点。例如,如果我有 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;
                 }
              }
          }
 }
 }

但是当我启动进程时,所有后台工作人员都启动了任务。任何人都可以帮助我吗?

提前谢谢..

【问题讨论】:

    标签: c# multithreading datagridview backgroundworker


    【解决方案1】:

    你想要做什么并不完全清楚。您的 click 方法为每个数据行启动一个新的 BackgroundWorker,但随后您的 DoWork 处理程序也为每一行执行内部循环。很混乱。我认为您想要的是启动 Max_Threads 工人,并让他们合作处理行。

    您在增加threadNumber 时遇到问题。增量不是原子操作,因此有可能两个线程同时递增它最终会相互踩踏。您需要同步对它的访问,可能使用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
        }
    }
    

    【讨论】:

    • 感谢您的代码,它运行良好。但我有一个疑问,在 callmethod 中,我为每个进程向 datagridview 提供状态消息,但它没有显示出来?你能告诉我为什么会这样吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多