【问题标题】:How to use Task.run to perform the function of Do_Work() of a background worker如何使用Task.run执行后台worker的Do_Work()功能
【发布时间】:2017-09-11 05:52:37
【问题描述】:

我在存储在路径列表中的特定路径中并行移动 4 个对象,当每个对象完成一条路径(特定坐标)时,它会切换到另一条路径!

我使用 4 个后台工作人员在后台执行这样的工作,在每次调用中,每个后台工作人员应该尝试从文本文件中提取的 6 个路径(染色体),每个路径存储在不同的 6 个列表中,每个列表包含坐标每条路径。然后将坐标转换为 2D 点以执行投影,并将特定深度的每个路径作为使用投影技术在不同层上移动这些对象的路径,即每个对象(工作人员)将在不同层移动。

每个工作人员应使用一条路径(染色体)向前和向后移动对象,然后切换到下一条,并且在切换到下一条之前,它应该完全完成第一次尝试(路径),以便计算消耗的时间和其他因素,例如“健身”功能。

以下是 Do_Work() 方法之一的示例:

    private void auv0Genetic_DoWork(object sender, DoWorkEventArgs e)
    {

        List<PointF> genetic2DLayerPath1 = new List<PointF>(); //  from chromosome 1
        List<PointF> genetic2DLayerPath2 = new List<PointF>(); //  from chromosome 2
        List<PointF> genetic2DLayerPath3 = new List<PointF>(); //  from chromosome 3
        List<PointF> genetic2DLayerPath4 = new List<PointF>(); //  from chromosome 4
        List<PointF> genetic2DLayerPath5 = new List<PointF>(); //  from chromosome 5
        List<PointF> genetic2DLayerPath6 = new List<PointF>(); //  from chromosome 6

        countNumOfPaths_auv_1 = 0;

        float[] xPoints = new float[1];
        float[] yPoints = new float[1]; 

        foreach (int[,] arr in pathChromosom1)
        {
            Point3D pointIn3D = new Point3D(cellsCenters[0, arr[0, 0]], cellsCenters[1, arr[1, 0]], 700);
            PointF pointIn2D = Project(pointIn3D); // convert to 2D
            genetic2DLayerPath1.Add(pointIn2D);
        }

        foreach (int[,] arr in pathChromosom2)
        {
            Point3D pointIn3D = new Point3D(cellsCenters[0, arr[0, 0]], cellsCenters[1, arr[1, 0]], 700);
            PointF pointIn2D = Project(pointIn3D); // convert to 2D
            genetic2DLayerPath2.Add(pointIn2D);
        }

        foreach (int[,] arr in pathChromosom3)
        {
            Point3D pointIn3D = new Point3D(cellsCenters[0, arr[0, 0]], cellsCenters[1, arr[1, 0]], 700);
            PointF pointIn2D = Project(pointIn3D); // convert to 2D
            genetic2DLayerPath3.Add(pointIn2D);
        }


        foreach (int[,] arr in pathChromosom4)
        {
            Point3D pointIn3D = new Point3D(cellsCenters[0, arr[0, 0]], cellsCenters[1, arr[1, 0]], 700);
            PointF pointIn2D = Project(pointIn3D); // convert to 2D
            genetic2DLayerPath4.Add(pointIn2D);
        }

        foreach (int[,] arr in pathChromosom5)
        {
            Point3D pointIn3D = new Point3D(cellsCenters[0, arr[0, 0]], cellsCenters[1, arr[1, 0]], 700);
            PointF pointIn2D = Project(pointIn3D); // convert to 2D
            genetic2DLayerPath5.Add(pointIn2D);
        }

        foreach (int[,] arr in pathChromosom6)
        {
            Point3D pointIn3D = new Point3D(cellsCenters[0, arr[0, 0]], cellsCenters[1, arr[1, 0]], 700);
            PointF pointIn2D = Project(pointIn3D); // convert to 2D
            genetic2DLayerPath6.Add(pointIn2D);
        }

        int counter = 0;

        for (int i = 0; i < 6; i++)
        {
            if (i == 0) // first chromosome
            {
                xPoints = new float[genetic2DLayerPath1.Count()];
                yPoints = new float[genetic2DLayerPath1.Count()];

                auv[0].auvDepth = 700;

                foreach(PointF p in genetic2DLayerPath1)
                {
                    xPoints[counter] = p.X;
                    yPoints[counter] = p.Y;
                    counter++;
                }
                counter = 0;
            }

            if (i == 1) // second chromosome
            {
                xPoints = new float[genetic2DLayerPath2.Count()];
                yPoints = new float[genetic2DLayerPath2.Count()];

                auv[0].auvDepth = 700;

                foreach (PointF p in genetic2DLayerPath2)
                {
                    xPoints[counter] = p.X;
                    yPoints[counter] = p.Y;
                    counter++;
                }
                counter = 0;
            }

            if (i == 2) // third chromosome
            {
                xPoints = new float[genetic2DLayerPath3.Count()];
                yPoints = new float[genetic2DLayerPath3.Count()];

                auv[0].auvDepth = 700;

                foreach (PointF p in genetic2DLayerPath3)
                {
                    xPoints[counter] = p.X;
                    yPoints[counter] = p.Y;
                    counter++;
                }
                counter = 0;
            }

            if (i == 3) // fourth chromosome
            {
                xPoints = new float[genetic2DLayerPath4.Count()];
                yPoints = new float[genetic2DLayerPath4.Count()];

                auv[0].auvDepth = 700;

                foreach (PointF p in genetic2DLayerPath4)
                {
                    xPoints[counter] = p.X;
                    yPoints[counter] = p.Y;
                    counter++;
                }
                counter = 0;
            }

            if (i == 4) // fifth chromosome
            {
                xPoints = new float[genetic2DLayerPath5.Count()];
                yPoints = new float[genetic2DLayerPath5.Count()];

                auv[0].auvDepth = 700;

                foreach (PointF p in genetic2DLayerPath5)
                {
                    xPoints[counter] = p.X;
                    yPoints[counter] = p.Y;
                    counter++;
                }
                counter = 0;
            }

            if (i == 5) // sixth chromosome
            {
                xPoints = new float[genetic2DLayerPath6.Count()];
                yPoints = new float[genetic2DLayerPath6.Count()];

                auv[0].auvDepth = 700;

                foreach (PointF p in genetic2DLayerPath6)
                {
                    xPoints[counter] = p.X;
                    yPoints[counter] = p.Y;
                    counter++;
                }
                counter = 0;
            }

            counter = 0;

                while (countNumOfPaths_auv_1 != 2)
                {
                    Thread.Sleep(900); // assume that it represents the speed of the AUV which is in our case = 3 m/s as each meter equal to 300 seconds in thread.sleep()  

                    if (auv0Genetic.CancellationPending)
                    {
                        e.Cancel = true;
                        return;
                    }

                    if (forward)
                    {
                        if (counter == xPoints.Length - 1)
                        {
                            backward = true;
                            forward = false;
                            countNumOfPaths_auv_1++;
                        }
                        else
                        {
                            auv[0].auvX = xPoints[counter];
                            auv[0].auvY = yPoints[counter];

                            counter++;
                        }
                    }

                    if (backward)
                    {
                        if (counter == 0)
                        {
                            backward = false;
                            forward = true;
                            countNumOfPaths_auv_1++;
                        }
                        else
                        {
                            auv[0].auvX = xPoints[counter];
                            auv[0].auvY = yPoints[counter];
                            counter--;
                        }
                    }

                    //////////////////////// Draw ///////////////////////////
                    iSetupDisplay = 0;

                    if (iSetupDisplay != -1)
                    {
                        iSetupDisplay += 10;
                        if (iSetupDisplay >= topology.Width)
                            iSetupDisplay = -1;
                        topology.Refresh();
                    }
                /////////////////////////////////////////////////////////
                }
        }

    }

我这样声明每个后台工作人员:

    auv0Genetic = new BackgroundWorker();

                    auv0Genetic.WorkerSupportsCancellation = true;

                    auv0Genetic.DoWork += new DoWorkEventHandler(auv0Genetic_DoWork);

                    auv0Genetic.RunWorkerCompleted += new 

RunWorkerCompletedEventHandler(auv0Genetic_RunWorkerCompleted);

我在一个循环中声明它们,循环 250 次,并在每次循环中调用它们,方法是调用另一个包含以下行的方法:

auv0Genetic.RunWorkerAsync(geneticIteration); // start AUV # 1

问题:

循环和Do_Work() 方法之间没有同步,即循环在 4 个后台工作人员完全完成工作之前开始新的迭代,其中每次迭代都有一个包含 6 个不同路径(染色体)的列表,每个后台工作人员应该在下一次迭代之前使用新列表尝试它们。在进行下一次迭代之前,我需要完全停止工作人员。我在循环之外放置了一个消息框,即使在所有工作人员停止之后,我也没有在循环完成后出现它。

我的问题是:

我在使用后台工作人员时遇到了一些问题,所以我想知道是否可以使用 Task 类,如果可以的话.. 那么如何使用 Task.runDo_Work() 方法中执行相同的工作?

【问题讨论】:

  • 因此,不是调查和解决您第一次尝试使用特定多线程机制时遇到的问题,而是通过再次尝试使用不同的多线程机制来解决问题?这不是有点像借钱还债吗?为什么我们不看看这些背景工作者的问题呢?诸如“我使用 4 个后台工作人员来操作 4 个对象并声明工作人员 250 次”之类的简单内容 - 嗯,似乎是一些问题的开始......
  • “借钱还清贷款”——在利率方面是有道理的......转移到问题:OP可能仍然有问题,但可能会解决她现在遇到的一些问题。此外,如果(我知道 - 如果)她计划在她的整体架构中采用 TPL / TAP,那么离开 BackgroundWorker 是合理的。在课程中,也可能对第一次尝试的问题有所启发。
  • Rose:只是一些改进的提示。您的 DoWork 方法包含 很多 重复代码。您可能希望显着减少它。然后,您似乎使用的资源不是 DoWork 方法的本地资源。这意味着您依靠“副作用”来收集结果等。这至少有一些气味。不过,为了给您提供体面的建议,我们必须知道您提到的问题是什么
  • 您要执行auv0Genetic_DoWork 总共 1000 次 - 一次 4 次,等待那些完成,然后开始下 4 次?
  • @Rose 对于这样的代码(一个大方法),BGW 与调用Task.Run(()=&gt;thatBigMethod()); 完全相同,而不是等待结果。 BGW 不会使方法内的循环以并行/并发/任何方式运行。如果您希望一个执行在另一个之前发生,您可以使用await Task.Run(()=FirstCall()); await Task.Run(()=&gt;SecondCall()); 等。

标签: c# multithreading task-parallel-library backgroundworker


【解决方案1】:

主要概念是:

public async Task WorkerStartedMethod()
{
    for(int i = 0; i<=250; i++)
    {
        List<Task> tasks = new List<Task>();
        tasks.add(Task.Run(auv0Genetic_DoWork));
        tasks.add(Task.Run(auv0Genetic_DoWork));
        tasks.add(Task.Run(auv0Genetic_DoWork));
        tasks.add(Task.Run(auv0Genetic_DoWork));
        tasks.add(Task.Run(auv0Genetic_DoWork));
        tasks.add(Task.Run(auv0Genetic_DoWork));
        await Task.WhenAll(tasks);
    }
}

但是,我假设应该重写“DoWork”方法,以防您需要访问 UI 线程。您应该在所有尝试更改 UI 内容的部分添加调度程序。

【讨论】:

    【解决方案2】:

    我能给出答案的假设:

    • 这会使用具有关联任务的对象,因为您听起来对使用任务很感兴趣,是的,它会比 jerryrigging 后台工作人员更顺畅。
    • 我将假设您了解您的业务逻辑和 我不需要。

    • 我将重点介绍一种使用选项以统一方式处理数据的方法 增加容量。

    • 我当然愿意修改和照亮不清楚的地方。

    • 这应该被认为是伪代码,我没有编译它,并且由于缺少想法,它不会编译。可能需要进行一些修改以解决小问题,因为我在这里追求的是大局观而不是细节。

    代码

    包括

    您将需要的包含:

    using System;
    using System.Threading.Tasks;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.IO;
    using System.Threading;
    using System.Diagnostics;
    

    处理循环

    这是您可以从单个后台工作人员调用的主循环:

    public void BeginProcess()
    {
        //This is the limitation on threads/cpu usage
        var maxWorkers = 4;
        //You could tackle how to go through the loop many ways this was how I was doing it for a simple file transfer program so I didn't change the paradigm
        var currentWorker = 0;
    
        //This is the Worker List that will hold and then run our chromosome business logic
        var ChromosomeWorkers = new List<ChromWorker>();
    
        //I am not sure based on the code how you are running through this, but here is a population example
        foreach (var chromTemplate in ChromosomeTemplates)
        {
    
            var cw = new ChromWorker(/*pass in appropriate arrays etc*/);
            ChromosomeWorkers.Add(cw);
    
    
                //If the count of Running workers is less than Max Workers and we are not at the end of the list Continue starting them
            if (ChromosomeWorkers.Count(x => x.Running) < maxWorkers && currentWorker < ChromosomeWorkers.Count)
            {
                ChromosomeWorkers[currentWorker].Start();
                currentWorker++;
            }
    
    
        }
    
    
        //Transition from Creation to Pure Processing
        do
        {
            if (ChromosomeWorkers.Count(x => x.Running) < maxWorkers && currentWorker < ChromosomeWorkers.Count)
            {
                FilesToBeTransferred[currentWorker].Start();
                currentWorker++;
            }
            else
            {
                //If the workers are maxed then sleep for a bit on this thread
                Thread.Sleep(150);
            }
        }
        while (currentWorker < ChromosomeWorkers.Count);
    
    
    }
    

    工人阶级

    注意:您可能需要考虑许多其他任务状态,例如 IsFaulted 等。我想保持简洁,所以我没有涉及这些情况,但您可能必须考虑他们。

    这是负责大部分步法的工人阶级:

    public class ChromWorker
    {
        private Task _t;
    
        bool isConsumed = false;
        pathChromosom1 [,];
        string _Key = string.Empty;
        List<Tag> _Tags = new List<Tag>();
    
        public ChromWorker(/*Data that might be useful in your worker*/)
        {
            pathChromosom1 = inChromosomeArrays;
    
    
        }
    
    
        public bool Running
        {
            get
            {
    
                if (_t == null || _t.IsCompleted ) return false;
    
                return true;
            }
        }
    
        public bool Done
        {
            get
            {
                return _t != null && _t.IsCompleted;
            }
        }
    
        public bool Ready
        {
            get { return _t == null; }
        }
    
        public void Start()
        {
            _t = new Task(_Run);
            _t.Start();
    
        }
    
        private void _Run()
        {
            double tries = 0;
            bool Handled = false;
            while (!Handled && tries < Math.Pow(10, 6))
            {
                //Increase our giveup loop
                tries++;
                try
                {
                    /* your Business logic */
                    Handled = true;
    
                }
                catch (Exception e)
                {
    
                    Console.WriteLine("Exception: {0} StackTrace: {1}", e.Message, e.StackTrace);
                }
    
            }
    
        }
    }
    

    【讨论】:

    • 我已经更新了我的问题,请看一下并注意我使用的是 VS 2012
    • 我不再是 2012 年的专家了。这是否意味着我使用的某些包含的库不可用?
    • @Rose 您是否认为如果有人遇到这么多麻烦,您应该确定哪些组件不可用? VS2012 supports .Net 4.5 并且此代码中没有任何内容。Net 4.5 不支持。下次请用 VS 或 .Net 版本标记您的问题,以设定期望并避免失望。
    • @Carter : 你能澄清你的答案吗...这不是一个完整的答案,有一些歧义!
    • 我只能想象你在谈论你正在做的实际工作,我们无法真正理解,因为我们不知道向前或向后的定义,甚至不知道它们在哪里定义。您将必须引入一些全局定义的变量及其用途,以便我接近弄清楚您的业务逻辑。
    猜你喜欢
    • 2013-02-24
    • 2015-08-23
    • 2014-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    相关资源
    最近更新 更多