当前位置:  开发笔记 > 编程语言 > 正文

推出成千上万的Backgroundworkers的正确方法?

如何解决《推出成千上万的Backgroundworkers的正确方法?》经验,为你挑选了1个好方法。

我写了一个程序,扫描网络中的10.000台计算机的正常运行时间,活动用户,空闲时间和ping.该计划表现很好.主要是在大约3分钟内检查所有计算机.但最近,该计划一直在冻结.它完成了所有任务,但不会退出.我像这样启动所有BackGroundWorkers:

foreach (DataRow computer in computerTable.Rows)
                {
                    //Added check to see if computer is in inputlist for inputfilemode
                    if (!inputFileMode || (inputFileMode && computerList.Contains(computer["ComputerName"].ToString())))
                    {
                        BackgroundWorker bw = new BackgroundWorker();
                        //Determine background jobs
                        bw.DoWork += bw_DoWork;
                        bw.RunWorkerCompleted += bw_RunWorkerCompleted;

                        bw.RunWorkerAsync(computer); //Start background worker
                        numberOfWorkers++;
                    }
                }


                int lastNr = 0;
                int skipHangingJobsCounter = 0;
                do
                {
                    lastNr = numberOfWorkers;
                    Thread.Sleep(1000);

                    Console.WriteLine("Tijd: " + DateTime.Now.ToString("yyyyMMdd-HH:mm:ss") + " #Jobs queued: " + numberOfWorkers.ToString() + " Jobs/sec: " + (lastNr - numberOfWorkers).ToString() + " -ForcedShutdowns: " + forcedReboots.ToString() + " -MSIEXEC Exceptions: " + machinesMSI.ToString()); //Report progress
                    if (lastNr - numberOfWorkers == 0)
                    {
                        skipHangingJobsCounter++;
                        if (skipHangingJobsCounter > 30) break; //Safety breakout if a worker hangs
                    }
                    else
                    {
                        skipHangingJobsCounter = 0;
                    }

                    //Timing break
                    double minutesRunning = DateTime.Now.Subtract(startOfJob).TotalMinutes;
                    if (minutesRunning > 13)
                    {
                        Console.WriteLine("Job is running for 14 minutes. Job will be cancelled. Jobs queued remaining: " + numberOfWorkers.ToString());
                        break;
                    }

                } while (numberOfWorkers > 0); //Wait till all jobs are finished

我想知道:这是启动和跟踪所有后台工作的最有效方式吗?最好是创建一个List数组吗?我认为这会占用大量内存,不是吗?

在do_work部分,我有很多WMI查询,正常运行时间等等.由于挂起WMI查询,我的程序是否会退出?有人试过这个吗?

所以我基本上有两个问题:

1-我是否以有效/正确的方式启动了背景工作者?

2-是否有可能线程中的WMI调用导致程序无法退出?

更新:

我重新编写了如下代码.它现在快了大约3倍.我仍然使用1个后台工作者,但仅限于,所以我可以在主线程上给出反馈.它应该工作的方式我认为:)

主线程:

                    BackgroundWorker bw = new BackgroundWorker();
                bw.DoWork += bw_DoWork;
                bw.RunWorkerCompleted +=bw_RunWorkerCompleted;
                bw.RunWorkerAsync();

                int lastNr = numberOfWorkers;
                do
                {
                    lastNr = numberOfWorkers;
                    Thread.Sleep(1000); //Give feedback every second

                    Console.WriteLine("Tijd: " + DateTime.Now.ToString("yyyyMMdd-HH:mm:ss") + " #Jobs queued: " + numberOfWorkers.ToString() + " Jobs/sec: " + (lastNr - numberOfWorkers).ToString() + " -ForcedShutdowns: " + forcedReboots.ToString() + " -MSIEXEC Exceptions: " + machinesMSI.ToString()); //Report progress

                    //Timing break
                    double minutesRunning = DateTime.Now.Subtract(startOfJob).TotalMinutes;
                    if (numberOfWorkers < 3)
                    {
                        //We are waiting for 3 last workers. Give feedback which 3 thse are
                        foreach (Task t in taskArray)
                        {
                            if (t.Status == TaskStatus.Running)
                            {
                                Console.WriteLine("Waiting for " + taskList[t.Id]);
                            }
                        }
                    }
                    if (minutesRunning > 13)
                    {
                        Console.WriteLine("Job is running for 14 minutes. Job will be cancelled. Jobs queued remaining: " + numberOfWorkers.ToString());
                        break;
                    }

                } while (!jobDone); //Wait till all jobs are finished

背景工作

        static void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        JobLauncher();
    }

    static void JobLauncher()
    {


        foreach (DataRow computer in computerTable.Rows)
        {
            //Added check to see if computer is in inputlist for inputfilemode
            if (!inputFileMode || (inputFileMode && computerList.Contains(computer["ComputerName"].ToString())))
            {
                Task t = Task.Factory.StartNew(() => CheckComputer(computer));
                taskList.Add(t.Id, computer["ComputerName"].ToString());
                taskArray.Add(t);

                numberOfWorkers++;
            }
        }

        Task.WaitAll(taskArray.ToArray());
    }

Patrick Hofm.. 5

而不是所有这些,您可以更好地使用预定义的方法来检查所有任务是否已经结束.您的代码如果非常容易出错并且可能会关闭整个应用程序.为什么为每台计算机启动1个线程?10.000个主题?这似乎有点矫枉过正.

我的建议是使用任务而不是后台工作人员.如果您有网络I/O,则最有可能的await是,提高整体性能.只是Task.WhenAll他们,你会注意到他们准备好了.

另一种方法是使用Parrallel库.你可以Parrallel.Foreach在计算机列表中将它们调整到最多16个左右,.NET框架将完成所有循环并检查你.



1> Patrick Hofm..:

而不是所有这些,您可以更好地使用预定义的方法来检查所有任务是否已经结束.您的代码如果非常容易出错并且可能会关闭整个应用程序.为什么为每台计算机启动1个线程?10.000个主题?这似乎有点矫枉过正.

我的建议是使用任务而不是后台工作人员.如果您有网络I/O,则最有可能的await是,提高整体性能.只是Task.WhenAll他们,你会注意到他们准备好了.

另一种方法是使用Parrallel库.你可以Parrallel.Foreach在计算机列表中将它们调整到最多16个左右,.NET框架将完成所有循环并检查你.

推荐阅读
喜生-Da
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有