Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net:后台工作程序和多CPU_C#_.net_Multithreading_Backgroundworker - Fatal编程技术网

C# .Net:后台工作程序和多CPU

C# .Net:后台工作程序和多CPU,c#,.net,multithreading,backgroundworker,C#,.net,Multithreading,Backgroundworker,我正在使用BackgroundWorker在后台做一些繁重的工作,这样UI就不会变得没有响应 但今天我注意到,当我运行我的程序时,两个CPU中只有一个被使用 是否有任何方法可以将所有CPU与BackgroundWorker一起使用 这是我的简化代码,如果你好奇的话 private void bwPatchApplier_DoWork(对象发送方,DoWorkEventArgs e) { 字符串pc1WorkflowName; 字符串pc2WorkflowName; 如果(!GetWorkf

我正在使用
BackgroundWorker
在后台做一些繁重的工作,这样UI就不会变得没有响应

但今天我注意到,当我运行我的程序时,两个CPU中只有一个被使用

是否有任何方法可以将所有CPU与
BackgroundWorker
一起使用

这是我的简化代码,如果你好奇的话



private void bwPatchApplier_DoWork(对象发送方,DoWorkEventArgs e)
{
字符串pc1WorkflowName;
字符串pc2WorkflowName;
如果(!GetWorkflowSettings(out pc1WorkflowName,out pc2WorkflowName))返回;
整数百分比=0;
var weworkspace=(List)e.参数;
foreach(WEWorkspace中的WEWorkspace)
{
使用(var spSite=newspsite(weWorkspace.SiteId))
{
foreach(spSite.AllWebs中的SPWeb)
{
使用(SPWeb SPWeb=spSite.OpenWeb(web.ID))
{
PrintHeader(spWeb.ID、spWeb.Title、spWeb.Url、bwPatchApplier);
尝试
{
对于(int index=0;index


非常感谢您对此进行深入研究:)

每个BackgroundWorker只使用一个线程来完成您让它完成的任务。要利用多个内核,您需要多个线程。这意味着多个BackgroundWorker或从DoWork方法中生成多个线程。

BackgroundWorker
在单个后台(线程池)线程中执行其工作。因此,如果计算量很大,它将大量使用一个CPU。UI线程仍在第二个线程上运行,但可能(像大多数用户界面工作一样)将几乎所有的时间都花在等待输入上(这是一件好事)


如果您想将工作分成多个CPU,则需要使用其他一些技术。这可能是多个
BackgroundWorker
组件,每个组件都做一些工作,或者直接使用线程池。在.NET4中,通过TPL简化了并行编程,这可能是一个非常好的选择。有关详细信息,您可以查看或。

BackgroundWorker正在第二个CPU内核上运行一个新线程,使UI保持响应


如果您使用的是.NET 4,请考虑使用,这样可以提供更好的结果并利用两个核心。

backgroundworker本身只提供一个额外的执行线程。它的目的是让事情脱离UI线程,而且它非常擅长这项工作。如果你想要更多的线程,你需要自己提供它们

这里很容易构建一个接受SPWeb参数的方法,只需为每个对象反复调用Thread.Start();然后使用Thread.Join()或WaitAll()完成,以等待它们在BackgroundWorker的末尾完成。但是,这不是一个好主意,因为操作系统会花费时间在所有线程之间执行上下文切换,从而降低效率


相反,您希望强制系统只在几个线程中运行,但至少在两个线程中运行(在本例中)。一个好的经验法则是(2n-1),其中“n”是您拥有的处理器内核数。。。但在各种情况下,你都想打破这条规则。您可以通过使用线程池来实现这一点,通过迭代您的SPWeb对象并将它们添加到您不断从中提取的队列,或者通过其他方式(如TPL)来实现。

BackgroundWorker本身只是在主UI之外创建一个线程来进行工作,而不是尝试在该工作线程中并行化操作。
private System.ComponentModel.BackgroundWorker bwPatchApplier;

this.bwPatchApplier.WorkerReportsProgress = true;
this.bwPatchApplier.DoWork += new System.ComponentModel.DoWorkEventHandler(this.bwPatchApplier_DoWork);
this.bwPatchApplier.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.bwPatchApplier_ProgressChanged);
this.bwPatchApplier.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.bwPatchApplier_RunWorkerCompleted);
private void bwPatchApplier_DoWork(object sender, DoWorkEventArgs e)
{
    string pc1WorkflowName;
    string pc2WorkflowName;

    if (!GetWorkflowSettings(out pc1WorkflowName, out pc2WorkflowName)) return;

    int progressPercentage = 0;
    var weWorkspaces = (List<WEWorkspace>) e.Argument;

    foreach (WEWorkspace weWorkspace in weWorkspaces)
    {
        using (var spSite = new SPSite(weWorkspace.SiteId))
        {
            foreach (SPWeb web in spSite.AllWebs)
            {
                using (SPWeb spWeb = spSite.OpenWeb(web.ID))
                {
                    PrintHeader(spWeb.ID, spWeb.Title, spWeb.Url, bwPatchApplier);

                    try
                    {
                        for (int index = 0; index < spWeb.Lists.Count; index++)
                        {
                            SPList spList = spWeb.Lists[index];

                            if (spList.Hidden) continue;

                            string listName = spList.Title;

                            if (listName.Equals("PC1") || listName.Equals("PC2"))
                            {
                                #region STEP 1

                                // STEP 1: Remove Workflow

                                #endregion

                                #region STEP 2

                                // STEP 2: Add Events: Adding & Updating

                                #endregion
                            }

                            if ((uint) spList.BaseTemplate == 10135 || (uint) spList.BaseTemplate == 10134)
                            {
                                #region STEP 3

                                // STEP 3: Configure Custom AssignedToEmail Property

                                #endregion

                                #region STEP 4

                                if (enableAssignToEmail)
                                {
                                    // STEP 4: Install AssignedTo events to Work lists
                                }

                                #endregion
                            }

                            #region STEP 5

                            // STEP 5 Install Notification Events

                            #endregion

                            #region STEP 6

                            // STEP 6 Install Report List Events

                            #endregion

                            progressPercentage += TotalSteps;
                            UpdatePercentage(progressPercentage, bwPatchApplier);
                        }
                    }
                    catch (Exception exception)
                    {
                        progressPercentage += TotalSteps;
                        UpdatePercentage(progressPercentage, bwPatchApplier);
                    }
                }
            }
        }
    }

    PrintMessage(string.Empty, bwPatchApplier);
    PrintMessage("*** Process Completed", bwPatchApplier);

    UpdateStatus("Process Completed", bwPatchApplier);
}
foreach (SPWeb web in spSite.AllWebs)
{
    //Your loop code here
}        
Parallel.Foreach(spSite.AllWebs, web =>
        {
          //Your loop code here
        });