Member 11247684 Ответов: 1

Как запустить тот же фоновый рабочий и остановить его внутри цикла в C#


Я написал следующий код для выполнения генетического алгоритма, который повторяется 10 раз, и каждый раз, когда я вызываю функцию "FitnessFunction", я использую фоновый рабочий для перемещения объекта по топологии, и как только он достигает определенной точки, я отменяю этот фоновый рабочий и возвращаюсь к функции "Genetic_Algorithm"...

К сожалению, я получил следующую ошибку, когда нажал на кнопку" MOVE-AUV-GAAPS", которая вызывает метод "Genetic_Algorithm" :

Cross-thread operation not valid: Control 'topology' accessed from a thread other than the thread it was created on...
и указать на:

while(true)
который находится в функции "AUVbackGWgenetic_DoWork".

Функция "Genetic_Algorithm" :

<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" :


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" :

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();
                }


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

            }




        }



Следующая ссылка содержит картинку для моего приложения WF : Здесь

Что я уже пробовал:

Мне нужно запускать фоновый рабочий процесс каждый раз, когда я вызываю функцию "FitnessFunction", которая отвечает за его остановку при определенном условии.

[no name]

"Операция перекрестного потока недопустима" означает именно то, что она говорит. Это можно исправить, не пытаясь получить доступ к элементам управления пользовательского интерфейса из потоков, которые им не владеют, или вызвать вызовы для обновления элементов управления пользовательского интерфейса в потоке пользовательского интерфейса. Небольшое исследование может иметь большое значение для решения ваших собственных проблем.

Member 11247684

как это исправить, не могли бы вы дать ответ?..
Я новичок в Си#
Все Тины в порядке прямо сейчас ожидайте этой проблемы ...

Philippe Mori

Самый простой способ решить проблему-позвонить ReportProgress с пользовательским объектом и иметь обработчик для этого. Используя отладчик, легко выяснить, где есть кросс-потоковые операции при условии, что вы остановитесь на исключениях. Это решение должно работать нормально при условии, что вам не нужно много общаться с пользовательским интерфейсом (скажем, менее 100 звонков в секунду). Если существует гораздо больше коммуникаций, то вам нужно будет потратить время на изучение многопоточности, чтобы вы могли писать эффективный код.

Philippe Mori

Если вы вручную добавите обработчик в FitnessFunction, затем вы должны удалить его, когда он больше не нужен, и убедиться, что вы не будете присоединять обработчик несколько раз, если эта функция вызывается более одного раза.

Member 11247684

не могли бы вы дать подробный ответ?.. и используйте мой код в качестве примера

1 Ответов

Рейтинг:
8

OriginalGriff

Почему вы каждый раз пытаетесь запустить один и тот же BackgroundWorker? Почему бы не создавать новый каждый раз и не запускать его с помощью одного и того же обработчика DoWork?

Я обновил свой вопрос ...
не могли бы вы помочь мне правильно реализовать это движение, которое каждый раз начинается с вызова метода "FitnessFunction" и останавливается, если условие выполнено, а затем возвращается к циклу в методе "GeneticAlgorithm".


Вам нужно смотреть на то, что вы делаете, и думать об этом.
Когда вы проверяете отмену в своем работнике, вы проверяете переменную уровня класса - но когда вы создаете новый экземпляр, вы перезаписываете его, поэтому старый код проверяет новый рабочий и продолжает работать, потому что новый - по определению - не был отменен.
Сбросьте работника уровня класса: используйте sender параметр обработчика DoWork и приведите его к экземпляру BackgroundWorker-затем проверьте отмену этого параметра.

Вероятно, вам также следует передавать популяцию своему работнику и восстанавливать результаты с помощью обработчика завершенных событий, а не передавать генерацию, которая не имеет ничего общего ни с чем другим в вашем коде. Вы понимаете, что я имею в виду? Вы передаете популяцию функции FitnessFunction - но не используете ее - и передаете генерацию рабочему, который не является частью цикла, вызывающего функцию!

Это действительно выглядит так, как будто вы забегаете вперед и гадаете, вместо того чтобы сидеть и планировать, что вам нужно сделать в первую очередь. И что вы запаниковали и попали в петлю случайных изменений в надежде, что это сработает несколько раз. Остановись, успокойся и сначала подумай. Тогда дизайн и код!


Member 11247684

Я попробовал это сделать и получил ту же проблему!!
не могли бы вы изменить мой код и реализовать свою идею более правильным способом, чем я

OriginalGriff

Нет, покажи мне, что ты пробовал!

Member 11247684

Я обновил свой вопрос ...
не могли бы вы помочь мне правильно реализовать это движение, которое каждый раз начинается с вызова метода "FitnessFunction" и останавливается, если условие выполнено, а затем возвращается к циклу в методе "GeneticAlgorithm".

OriginalGriff

Ответ обновлен.

Member 11247684

спасибо за ваше обновление...
в этом коде я стремился показать, как использовать фоновых работников, теперь я работаю над этой функцией, используя популяцию (y)