Страница 1 из 1

проблема с lable

Добавлено: 19 апр 2015, 03:30
Крылья
ребят такая тема, в общем я создал форму на с++, там сделал кнопку, и по нажатии кнопки у меня секунда 20 будет выполняться метод, после того как он выполнится должно выводиться в lable слово "тик", потом я снова вызываю тот же метод который 20 секунд длиться и уже должно вывести в lable слово "так"..........при запуске он через некоторое время сразу выводит "так" помогите кто знает, что нужно подправить???..вот код:

Код: Выделить всё

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
			
				
		                         ppp1();                                //метод выполняется 20 секунд
				 this->label4->Text = "тик";   //вывести тик
				 ppp1();                               //метод выполняется 20 секунд
				 this->label4->Text = "так";  //вывести так

	}

Re: проблема с lable

Добавлено: 19 апр 2015, 13:16
Decoder
После того, как у оконного элемента изменился текст или какой-то иной визуальный параметр, должна произойти перерисовка окна, чтобы эти изменения были видны.
Но поскольку ты не даёшь окну обновиться, а сразу же запускаешь снова процедуру ppp1(), то функция обработчика оконных сообщений блокируется вплоть до завершения всего метода System::Void button1_Click.
Следовательно, когда произойдёт перерисовка окна, будет отображено лишь последнее значение строки this->label4->Text.
Решается это при помощи вывода данной процедуры в отдельный поток. Т.е. всё то, что написано в методе System::Void button1_Click, должно выполняться в отдельном потоке, тогда процедура обработчика оконных сообщений не будет блокироваться и перерисовка окна будет выполняться своевременно.

Re: проблема с lable

Добавлено: 19 апр 2015, 16:31
Крылья
я попытался сделать так, но почему-то у меня визуалка ругается на библиотеку
#include <thread>, пишет:
"Ошибка error C1189: #error : <thread> is not supported when compiling with /clr or /clr :p ure"

и когда пытаюсь вызвать процедуру в отдельном потоке "std::thread t1(threadFunction);" он ругается на процедуру "threadFunction".........и в конечном итоге у меня будет он поочередно отображаться?????? буду рад если поможете добиться работоспособности программы))

Код: Выделить всё

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
					
				 std::thread t1(threadFunction);
				 t1.join();

	}
		
			 void threadFunction()
			 {
				  ppp1();
				  this->label4->Text = "тик";
				  ppp1();
				  this->label4->Text = "так";
			 }

Re: проблема с lable

Добавлено: 20 апр 2015, 13:00
Decoder
Вместо класса std::thread нужно использовать соответствующий CLR-класс System::Threading::Thread


Документацию по нему и пример использования можешь посмотреть здесь:
https://msdn.microsoft.com/ru-ru/librar ... .110).aspx

Re: проблема с lable

Добавлено: 21 апр 2015, 09:42
WinMain
На первый взгляд всё вроде бы правильно сказано и про обработку оконных сообщений и про отдельный поток, но вот в предложенной реализации есть серьёзный изъян. Если просто тупо перенести текст метода button1_Click в другой метод, который запускается в отдельном потоке, то программа конечно скомпилируется без проблем и даже запустится. Но вот при выполнении этого поточного метода, когда дело дойдёт до изменения текста контрола, будет выброшено исключение с уведомлением о том, что к визуальным элементам формы нельзя напрямую обращаться из другого потока. Вот в этом и есть главная засада, о которой Decоder видимо не знал. Так что если уж браться за многопоточное программирование, то нужно как следует изучить механизмы синхронизации, оповещения и т.д.

Re: проблема с lable

Добавлено: 21 апр 2015, 11:04
Romeo
Не силён в .NET, но хорошо знаю программирование под Win32 API на С++, возможно это поможет.

На Win32 API эта задача решается отсылкой сообщения на изменение текста (WM_SETTEXT) из дочерней треды (на сообщения никаких запретов не налагается), в то время как главная треда должна ждать на хэндле дочерней треды (скажем, используя WaitForSingleObject) какое-то небольшое время, и если объект не просигнален, то каждый раз делать свой собственный пампинг мессейджей, тогда она в конце концов дойдёт то дого сообщения, которое было сгенерировано дочерним потоком и обработает его. Если же просигнален, значит дочерняя треда завешена, и мы можем выйти из цикла ожидания и пампинга, и идти дальше.

Re: проблема с lable

Добавлено: 21 апр 2015, 13:13
WinMain
На Win32 API степень свободы для системного программирования конечно больше, чем на .NET, но и здесь имеются кое-какие лазейки. Например, можно вызывать метод Invalidate() для объекта формы, что приводит к перерисовке окна. Таким образом в класс формы диалога можно добавить строковую переменную, через которую потом передавать отображаемый текст, а при перерисовке окна самим рисовать нужную строку вместо статического контрола. Визуально не будет никакой разницы. При этом сам контрол с формы можно не удалять, а только очистить его текст, чтобы он стал пустым. Он понадобится для обозначения местоположения на форме.

Вот как это будет выглядеть на C#

Код: Выделить всё

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            // Создание отдельного потока для windowThreadProc()
            System.Threading.ThreadStart threadStart = new System.Threading.ThreadStart(windowThreadProc);
            System.Threading.Thread thread = new System.Threading.Thread(threadStart);
            thread.Start();
        }

        private void windowThreadProc()
        {
            // Выполняется в отдельном потоке
            labelText = "Hello world!";
            Invalidate();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            // Отрисовка текста...
            e.Graphics.DrawString(labelText, SystemFonts.DefaultFont, SystemBrushes.WindowText, label1.Location);
        }

        private string labelText = "";

    }
Ну а перевести его на С++ не составляет особого труда.