Click here to Skip to main content
15,885,244 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I wrote the following code to perform genetic algorithm that loops 10 times and each time I call the "FitnessFunction" function, I use a background worker to move an object on the topology and once it reach a specific point then I cancel that background worker and back to the "Genetic_Algorithm" function...

Unfortunately, I got the following error when I click on "MOVE-AUV-GAAPS" button which call the "Genetic_Algorithm" method:

Cross-thread operation not valid: Control 'topology' accessed from a thread other than the thread it was created on...
and point to:

C#
while(true)
which is in the "AUVbackGWgenetic_DoWork" function.

"Genetic_Algorithm" function :

C#
<pre>        static int geneticIteration;

        static BackgroundWorker AUVbackGWgenetic;

        public void Genetic_Algorithm(int[][,] population)
        {

       

            double[,] FitnessValue = new double[6, 2]; // for all five chromosome we store two Values the Fitness Value and the Fitness Ratio

            int[] RouletteWheel = new int[6];

            int round=0;



            for (int geneticIteration = 0; geneticIteration < 10; geneticIteration++)

            {


                round = geneticIteration + 1;

                writer = new StreamWriter("C:/Users/Welcome/Desktop/listOfChromosomesForAllRounds.txt", true);


                writer.WriteLine("----------------------------------------------------------------------");

                
                Chromosomes(population,round);


                // Calculate the fitness Function and the Fitness Ratio
                
                FitnessFunction(population); // Fitness Function

                //RouletteWheel = RouletteWheel_Selection(population,FitnessValue); // Selection

                //population = CrosssOver(RouletteWheel, population); //Cross Over 

                //population = Mutation(RouletteWheel, population); // Mutation

                writer.Close();

   

            }


            //Store best path in the array as a group of XY coordinates 

            //for(int i=0;i<auvChromosomes.Length;i++)

            //{






            // }


            //completeAUVMovement(int[,]auvPath);


       }




"FitnessFunction" function :


C#
public void FitnessFunction(int[][,] population)
        {

double[,] FitnessValue = new double[6, 2]; // for all five chromosome we store two Values the Fitness Value and the Fitness Ratio

                AUVbackGWgenetic = new BackgroundWorker();

                AUVbackGWgenetic.DoWork += new DoWorkEventHandler (AUVbackGWgenetic_DoWork);

            AUVbackGWgenetic.RunWorkerAsync(geneticIteration);


            

        }


"AUVbackGWgenetic_DoWork" function :

C#
private void AUVbackGWgenetic_DoWork(object sender, DoWorkEventArgs e)
        
        {

            

            Random rnd = new Random();

            SoundPlayer player = new SoundPlayer("C:/Users/Welcome/Desktop/project/GAAPS/Sonar_pings.wav");

            auv.auvX = rnd.Next(200, 325);
            auv.auvY = rnd.Next(200, 325);

            while (true)
            {


                Thread.Sleep(300); // assume that it represents the speed of the AUV which is in our case = 3 m/s 

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




                if (auv.auvY == 200)
                {
                    if (auv.queue1.Count != 0)
                    {
                        Thread.Sleep(1000);


                        foreach (Packet packet in auv.queue1)
                        {
                            auv.SendToSink(packet);
                        }

                        auv.queue1.Clear();
                        topology.CreateGraphics().DrawString("Received Aggrigated Data from AUV # " + auv.auvID, new Font("Times New Roman", 7.0f), Brushes.Red, sink.sinkX - 48, sink.sinkY - 15); // Display the sink name
                        topology.CreateGraphics().DrawLine(dash, auv.auvX, auv.auvY, sink.sinkX + 20, sink.sinkY + 45);
                        player.Play();
                        Thread.Sleep(3000);
                        player.Stop();

                    }

                }


                if (forward)
                {
                    auv.auvX += 3;

                    auv.auvY += 3;



                    if (auv.auvY >= 326)
                    {

                        backward = true;

                        forward = false;

                        countNumOfPaths++;

                    }

                }

                if (backward)
                {

                    auv.auvX -= 3;

                    auv.auvY -= 3;


                    if (auv.auvY >= 200)
                    {

                        backward = false;

                        forward = true;

                        countNumOfPaths++;

                    }


                    if (countNumOfPaths >= 2)
                    {


                        AUVbackGWgenetic.CancelAsync();
                       
                    }


                }



                //////////////////////// Draw ///////////////////////////

                iSetupDisplay = 0;

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


                /////////////////////////////////////////////////////////

            }




        }



The following link contains a picture for my WF App : Here

What I have tried:

I need to run the background worker each time I call "FitnessFunction" function" which is responsible to stop it under a specific condition.
Posted
Updated 15-May-17 8:56am
v3
Comments
[no name] 15-May-17 15:07pm    
"Cross-thread operation not valid" means exactly what it says. You fix that by not trying to access UI controls from threads that do not own them or invoke the calls to update the UI controls to the UI thread. A little bit of research can go a long way to solving your own problems.
Member 11247684 15-May-17 15:10pm    
how to fix that, could you put an answer ...
I am a beginner in c#
All thins are ok right now expect this problem ...
Philippe Mori 15-May-17 20:06pm    
The easy way to solve the problem is to call ReportProgress with a user object and have an handler for that. Using the debugger, it is easy to figure out where there are cross-thread operation provide that you stop on exceptions. That solution should work fine provide that you don't need to much communication with the UI (say less than 100 calls per second). If there is much more communications, then you would need to invest time learning multithreading so that you could write efficient code.
Philippe Mori 15-May-17 20:09pm    
If you manually add an handler in FitnessFunction, then you have to remove it when not needed anymore and ensure that you won't attach the handler multiple times if that function is called more than once.
Member 11247684 15-May-17 22:23pm    
could you put a detailed answer ... and use my code as example

1 solution

Why are you trying to run the same BackgroundWorker each time? Why not create a new one each time and start that using the same DoWork handler?

I've updated my question ...
could you help me please to implement this movement correctly which starts on calling the "FitnessFunction" method each time and stops if the condition is satisfied and then back to the loop in the "GeneticAlgorithm" method.


You need to look at what you are doing, and think about it.
When you check for cancellation in your worker, you check the class level variable - but when you create a new instance, you overwrite it, so the old code checks the new worker, and continues to run because the new one - by definition - hasn't been cancelled.
Dump the class level worker: use the sender parameter of the DoWork handler and cast it to a BackgroundWorker instance - then check the cancellation on that.

You should probably also be passing the population to your worker, and recovering the results via the Completed event handler, rather than passing a genericIteration that has nothing to do with anything else in your code. Do you see what I mean? You pass a population to the FitnessFunction - but don't use it - and pass a genericIteration to the worker that isn't part of the loop that calls the function!

It does look like you are getting ahead of yourself and guessing instead of sitting down and planning what you need to do first. And that you have panicked and got round a loop of random changes in the hope that it'll work several times. Stop, calm down, and think first. Then design and code!
 
Share this answer
 
v2
Comments
Member 11247684 15-May-17 14:11pm    
I tried this and got the same problem!!
could you alter my code and implement your idea in a correct way than me
OriginalGriff 15-May-17 14:12pm    
No, show me what you tried!
Member 11247684 15-May-17 14:57pm    
I've updated my question ...
could you help me please to implement this movement correctly which starts on calling the "FitnessFunction" method each time and stops if the condition is satisfied and then back to the loop in the "GeneticAlgorithm" method.
OriginalGriff 16-May-17 5:13am    
Answer updated.
Member 11247684 16-May-17 8:56am    
thank you for your update...
in this code I aimed to show how to use background workers, now I am working on this function using the population (y)

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900