andycruce Ответов: 3

Создание экземпляра класса вызывает переполнение стека


Я пытаюсь создать решение, которое позволит потоку обновлять свойства WinForm (текстовое поле) при обработке данных в фоновом режиме. Я собрал" примерный " проект, который запускает поток для обновления WinForm во время работы основной программы.

Вот основная форма класса:

namespace Thread_Test_Sending_Data_to_Thread_Function
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            int i;
            InitializeComponent();
            FormData FormData1 = new FormData();
            Thread1 MyThread = new Thread1();

 
            for (i=0; i<10; i++)
            {
                FormData1.Label1Data = i;
                FormData1.Label1Data = i * 10;

                Thread WriteScreen = new Thread(delegate ()
                {
                    MyThread.FormWriteMethod(FormData1);
                });

                WriteScreen.Start();
                Thread.Sleep(1000);
            }
           
        }

а вот и класс thread

namespace Thread_Test_Sending_Data_to_Thread_Function
{
    public class Thread1 : Form1
    {
        private delegate void SetLabelTextDelegate(FormData InputClass);
        public void FormWriteMethod(FormData InputClass)
        {
            if (TestLabel1.InvokeRequired)
            {
                TestLabel1.BeginInvoke(new SetLabelTextDelegate(FormWriteMethod), new object[] { InputClass });
                return;
            }
            TestLabel1.Text = InputClass.Label1Data.ToString();
            TestLabel2.Text = InputClass.Label2Data.ToString();
        }
    }
}

Все строится нормально. Я полагаю, что настроил это так, чтобы позволить мне отправить ссылку на класс FormData в поток. FormData загружается основной программой формы,которая затем вызывает выполнение потока. Он делает паузу для завершения потока, а затем обновляет данные формы. Поток унаследовал Form1, поэтому он должен иметь доступ к текстовому полю TestLable1, определенному в Form1

Когда я пытаюсь запустить программу, программа попадает в оператор Thread1 MyThread = new Thread (); а затем возвращается к началу программы до тех пор, пока не произойдет переполнение стека. Должно быть, я упускаю что-то простое. Есть предложения?

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

Я рассмотрел множество примеров того, как отправлять данные в поток и как получить доступ к данным WinForm из потока. Из того, что я обнаружил, то, что я делаю, кажется правильным. Не уверен, что следует попробовать в следующем.

Mehdi Gholam

Почему нитки?

3 Ответов

Рейтинг:
22

OriginalGriff

Простой:

public Form1()
{
    int i;
    InitializeComponent();
    FormData FormData1 = new FormData();
    Thread1 MyThread = new Thread1();

И
public class Thread1 : Form1

Поскольку Thread1 является производным от Form1, при создании нового экземпляра Thread1 вызывается конструктор Form1, который создает экземпляр Thread1, который вызывает свой собственный конструктор Form1, который создает как экземпляр Thread1, который вызывает ...

В какой-то момент в системе заканчивается стековая память для хранения всех своих обратных адресов, и ваше приложение выходит из строя.


Рейтинг:
2

Patrice T

Ошибка здесь, вы храните 2 значения в одном объекте.

FormData1.Label1Data = i;
FormData1.Label1Data = i * 10;

Вы также можете удалить первую строку.

Я не знаю, что вы имеете в виду, но вы находитесь в цикле, и это значение является единственным способом для 2 потоков отличить друг от друга, но поскольку это объект и что значение постоянно меняется, это разрушает идею присвоения числа каждому потоку. Вы создаете нити, которые соревнуются друг с другом ?


Рейтинг:
18

Dave Kreskowiak

Здесь тааак много чего не так, и я не знаю, с чего начать.

Но я скажу вам, что он вызывает переполнение стека, потому что Form1 создает экземпляр Thread1. Thread1 наследует от класса form1, который создает экземпляр Thread1, который наследуется от класса form1, который создает предварительная из Thread1, который наследуется от класса form1, который создает экземпляр Thread1, который наследуется от класса form1, который создает экземпляр Thread1, ... взяли еще? Это то, что запускает стек.

Я понятия не имею, почему у вас есть Thread1, наследующий от Form1 вообще. Делегат и методы обновления метки должны находиться в форме 1.

Работа, которую вы выполняете в форме 1, должна быть где-то еще. Я не знаю, как Thread1?

У вас есть LabelData1, заданный двумя последовательными строками, которые вообще не сделают ничего полезного. Первое значение никогда не будет нарисовано на экране, потому что поток пользовательского интерфейса все равно будет зависать, выполняя код, устанавливающий LabelData1 на i*10.

Это слишком сложно с кодом во всех неправильных классах.


Midi_Mick

Я думаю, глядя на код, что 2 - е присвоение Label1Data-это просто опечатка-должно быть Label2Data.
В остальном все комментарии хороши. Однако если он удалит наследование Thread1 из Form1 и исправит опечатку, я думаю, что это действительно может сработать так, как он ожидает. Не красавица, но работает. Возможно, ему также придется подать заявление.DoEvents () вызывается после сна, чтобы получить обновления, отображаемые через соответствующие промежутки времени, а не все происходящие в конце.

Dave Kreskowiak

Приложение.DoEvents-это короткий путь для ужасной практики. Никогда не рекомендую его использовать.