Страница 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

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 = "";
}
Ну а перевести его на С++ не составляет особого труда.