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