I move 4 objects in parallel in a specific paths stored in a list of paths, when each of them complete one path(specific coordinates) it switches to another!.
I used 4 background workers to perform such a job in background and in each call each background worker should try 6 paths (chromosomes) extracted from an a text file and each path stored in different 6 lists and each list contains the coordinates for each path. The coordinates then converted to 2D points to perform projection and each path at a specific depth as the paths to move these objects on different layers using a projection technique i.e. ach object (worker) will be moved at different layer.
Each worker should move the object forward and backward using one path (chromosome) then switches to the next and it should finish the first attempt (path) completely before switch to next in order to calculate the time consumed and other factors such as "Fitness" function.
The following is an example on one the Do_Work() methods:
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();
}
/////////////////////////////////////////////////////////
}
}
}
I declared each background worker like this:
auv0Genetic = new BackgroundWorker();
auv0Genetic.WorkerSupportsCancellation = true;
auv0Genetic.DoWork += new DoWorkEventHandler(auv0Genetic_DoWork);
auv0Genetic.RunWorkerCompleted += new
RunWorkerCompletedEventHandler(auv0Genetic_RunWorkerCompleted);
I declared them in a loop that loops 250 times and call them inside this loop each time by calling another method that contains the following lines:
auv0Genetic.RunWorkerAsync(geneticIteration); // start AUV # 1
Problems :
There is no synchronization between the loop and the Do_Work()
method i.e. the loop starts new iteration before the 4 backgrounds worker finishes their work completely where for each iteration there is a list contains 6 different paths (chromosomes) and each background worker should tries them before the next iteration with the new list. I need to stop the workers completely before going to the next iteration. I put a message box outside the loop and I do not get it appeared after the completion of the loop even after all the workers stop.
My Question Is:
I faced some problems with using background workers so I wondered if it is possible to use Task class instead, if so .. then how to use Task.run
to perform the same job inside Do_Work()
methods ?
My Assumptions to be able to give an answer:
I am going to assume that you understand your business logic and there is no need for me to.
I will focus on a way to process data in a uniform way with options to increase capacity.
Of course I am willing to amend and illuminate unclear areas.
This should be considered Psuedo Code, I did not compile this and with the missing ideas it would not compile. Some edits to fix small things may be needed as I was going for the big picture idea here not the details.
THE CODE
INCLUDES
The Includes you will need:
PROCESSING LOOP
This is the main loop you could call this from a single background worker:
WORKER CLASS
NOTE: There are a lot of other Task states you might have to account for like IsFaulted, etc. I wanted to keep this concise so I did not go into those cases but you might have to account for them.
This is the worker class which will do most of the footwork:
The main concept is:
However I have an assumption that "DoWork" method should be rewritten in case you need access to the UI thread. You should add dispatchers in all parts where you try change something on the UI.