Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > C++

Ответ
 
Опции темы
Старый 22.02.2013, 00:57   #1
ІГРОГРАЙКО
ПроЭктировщик
 
Аватар для ІГРОГРАЙКО
 
Регистрация: 20.06.2009
Адрес: Україна
Сообщений: 152
Написано 10 полезных сообщений
(для 24 пользователей)
Доступ к GUI с иного потока

Добрый вечер вам!

CLR приложение (.Net средствами С++).
У меня есть форма, в форме есть контролы такие как кнопка, прогрес-бар, дата-грид-виев (таблица).
Все ето создавалось в основном потоке.
У меня появился новый поток после клика на кнопку и етот поток должен:
  • перерисовывать прогрес-бар
  • добавлять ечейки в дата-грид-виев
  • установить доступность (Enabled) кнопки в значение "true"
Вот код где состоялся клик и запустился новый поток:
	public:
		Thread^ processing;
		FileBase^ fileBase;

...

	private: System::Void buttonStart_Click(System::Object^  sender, System::EventArgs^  e) {
				 buttonStart->Enabled = false;
				 resultView->Rows->Clear();
				 array<String^>^ tmp = gcnew array<String^>(directoryList->Items->Count);
				 directoryList->Items->CopyTo(tmp,0);
				 fileBase = gcnew FileBase(tmp, checkboxSearchSubdir->Checked);
				 ThreadStart^ fileBaseDelegate = gcnew ThreadStart(this, &mainForm::DoProcessing);
				 processing = gcnew	Thread(fileBaseDelegate);
				 processing->Start();
			 }
Вот код функции что будет выполнять поток:
	public: void DoProcessing()
			{
				progressBar->Value = 0;
				progressBar->Maximum = fileBase->candidates->Count;
				for each(KeyValuePair<String^,Int64> iCandidate in fileBase->candidates)
				{
					if (fileBase->IsDuplicate(iCandidate))
					resultView->Rows->Add(iCandidate.Key , iCandidate.Value.ToString());
					progressBar->Value++;
				}
				buttonStart->Enabled = true;
			}
Но сразу же после старта потока вылетает екзепшн:
Нажмите на изображение для увеличения
Название: exception.png
Просмотров: 1104
Размер:	23.3 Кб
ID:	18837

Пожалуйста подскажите, как это лучше исправить! Можно ли обойтись без множества блоков try-catch?
Заранее спасибо!
__________________
Blitz3D, XNA, WebGL, OpenGL, Unity3D
PC: ASUS A55VM Core i3 (2.4Ghz), 6 Gb RAM, Nvidia GF 630M GT 2Gb
(Offline)
 
Ответить с цитированием
Старый 22.02.2013, 13:20   #2
h1dd3n
Бывалый
 
Аватар для h1dd3n
 
Регистрация: 19.06.2008
Сообщений: 679
Написано 264 полезных сообщений
(для 450 пользователей)
Ответ: Доступ к GUI с иного потока

Invoke();
__________________
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
ІГРОГРАЙКО (22.02.2013)
Старый 22.02.2013, 19:51   #3
ІГРОГРАЙКО
ПроЭктировщик
 
Аватар для ІГРОГРАЙКО
 
Регистрация: 20.06.2009
Адрес: Україна
Сообщений: 152
Написано 10 полезных сообщений
(для 24 пользователей)
Ответ: Доступ к GUI с иного потока

Да! Спасибочки!
Но как пользоваться этим Invoke() ???

Уже настрочил делегатов:
public: delegate void MyDel();
...
	public: void DoProcessing()
			{
				MyDel^ DelInst = gcnew MyDel(this, &mainForm::CleanProgressBar);
				if (progressBar->InvokeRequired)
					DelInst->Invoke();
				DelInst = gcnew MyDel(this, &mainForm::ResetProgressBar);
				if (progressBar->InvokeRequired)
					DelInst->Invoke();

				for each(KeyValuePair<String^,Int64> iCandidate in fileBase->candidates)
				{
					if (fileBase->IsDuplicate(iCandidate))
					resultView->Rows->Add(iCandidate.Key , iCandidate.Value.ToString());
					progressBar->Value++;
				}
				buttonStart->Enabled = true;
			}

...

	public: void CleanProgressBar()
			{
				progressBar->Value = 1;
			}

	public: void ResetProgressBar()
			{
				progressBar->Maximum = fileBase->candidates->Count;
			}
Но все тот же екзепшн вылазит!
Сразу же при: progressBar->Value = 1;
__________________
Blitz3D, XNA, WebGL, OpenGL, Unity3D
PC: ASUS A55VM Core i3 (2.4Ghz), 6 Gb RAM, Nvidia GF 630M GT 2Gb
(Offline)
 
Ответить с цитированием
Старый 22.02.2013, 23:12   #4
h1dd3n
Бывалый
 
Аватар для h1dd3n
 
Регистрация: 19.06.2008
Сообщений: 679
Написано 264 полезных сообщений
(для 450 пользователей)
Ответ: Доступ к GUI с иного потока

В принципе правильное решение - это события, но когда тебе просто надо обновить прогресс бар, воротить систему событий как-то не хочется, поэтому проще воспользоваться методом Invoke.
Скопировал из своего (Это C#, но суть все равно одна):
public partial class MainForm : Form
{
//Вот сюда стоит обратить внимание
    private delegate void LogDelegate(string loginfo, Color clr);
    private readonly LogDelegate _logPtr; //readonly не обязательно
    
    public MainForm()
    {
        _logPtr = Log; //И сюда
    }
    private void Log(string loginfo, Color clr)
    {
        textboxLogConnection.SelectionStart = textboxLogConnection.Text.Length;
        textboxLogConnection.SelectionColor = clr;
        textboxLogConnection.SelectionFont = new Font(textboxLogConnection.SelectionFont, FontStyle.Bold);
        textboxLogConnection.AppendText(string.Format("[{0:00}:{1:00}:{2:00}] ", DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second));
        textboxLogConnection.AppendText(loginfo + "\n");
    }
Далее там где мне надо что-то занести в лог я просто пишу
Invoke(_logPtr, "SOME MESSAGE", Color.Black);
и не парюсь о потоках.
__________________
(Offline)
 
Ответить с цитированием
Старый 24.02.2013, 00:07   #5
impersonalis
Зануда с интернетом
 
Аватар для impersonalis
 
Регистрация: 04.09.2005
Сообщений: 14,014
Написано 6,798 полезных сообщений
(для 20,935 пользователей)
Ответ: Доступ к GUI с иного потока

[критикан]
Всё какие-то свиристелки. Почему б не использовать WinAPI? Или тут что-то про кросплатформенность - тогда Boost?[/критикан]
В своё время, когда решал подобную задачу (два потока - один постоянно крутит цикл с рассчётами, второй - ГУИ: обрабатывает кнопочки и с некоторой невысокой частотой обновляет данные о работе первого потока) опирался на статью "Организация межпотокового взаимодействия с использованием объектов ядра операционной системы" (в журнале "Вестник компьютерных и информационных технологий")
__________________
http://nabatchikov.com
Мир нужно делать лучше и чище. Иначе, зачем мы живем? tormoz
А я растила сына на преданьях
о принцах, троллях, потайных свиданьях,
погонях, похищениях невест.
Да кто же знал, что сказка душу съест?
(Offline)
 
Ответить с цитированием
Старый 24.02.2013, 18:20   #6
h1dd3n
Бывалый
 
Аватар для h1dd3n
 
Регистрация: 19.06.2008
Сообщений: 679
Написано 264 полезных сообщений
(для 450 пользователей)
Ответ: Доступ к GUI с иного потока

Сообщение от impersonalis Посмотреть сообщение
[критикан]
Всё какие-то свиристелки. Почему б не использовать WinAPI? Или тут что-то про кросплатформенность - тогда Boost?[/критикан]
В своё время, когда решал подобную задачу (два потока - один постоянно крутит цикл с рассчётами, второй - ГУИ: обрабатывает кнопочки и с некоторой невысокой частотой обновляет данные о работе первого потока) опирался на статью "Организация межпотокового взаимодействия с использованием объектов ядра операционной системы" (в журнале "Вестник компьютерных и информационных технологий")
CLR приложение (.Net средствами С++).
..
__________________
(Offline)
 
Ответить с цитированием
Старый 26.02.2013, 18:20   #7
ІГРОГРАЙКО
ПроЭктировщик
 
Аватар для ІГРОГРАЙКО
 
Регистрация: 20.06.2009
Адрес: Україна
Сообщений: 152
Написано 10 полезных сообщений
(для 24 пользователей)
Ответ: Доступ к GUI с иного потока

Спасибо большое за розяснения.
У меня было времени в обрез потому, я все переделал на BackgroundWorker...

Вот пример:
private: System::ComponentModel::BackgroundWorker^  backgroundWorker;
FileBase^ fileBase;

...

	private: System::Void buttonStart_Click(System::Object^  sender, System::EventArgs^  e) {
				buttonStart->Enabled = false;
				buttonCancel->Enabled = true;
				resultView->Rows->Clear();
				array<String^>^ tmp = gcnew array<String^>(directoryList->Items->Count);
				directoryList->Items->CopyTo(tmp,0);
				fileBase = gcnew FileBase(tmp, checkboxSearchSubdir->Checked);
				progressBar->Value = 0;
				backgroundWorker->RunWorkerAsync();
			 }

	private: System::Void buttonCancel_Click(System::Object^  sender, System::EventArgs^  e) {
				backgroundWorker->CancelAsync();
				buttonCancel->Enabled = false;
				buttonStart->Enabled = true;
				progressBar->Value = 0;
			 }

	private: System::Void backgroundWorker_DoWork(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) {
				int counter = 0;
				int percentsComplited = 0;
				for each(KeyValuePair<String^,Int64> iCandidate in fileBase->candidates)
				{
					if (backgroundWorker->CancellationPending)
					{
						return;
					}

					counter++;
					percentsComplited = (counter * 100)/fileBase->candidates->Count;
					if (fileBase->IsDuplicate(iCandidate))
						backgroundWorker->ReportProgress(percentsComplited,iCandidate.Key + "*" + iCandidate.Value.ToString());
					else
						backgroundWorker->ReportProgress(percentsComplited,"");
				}
			 }

	private: System::Void backgroundWorker_ProgressChanged(System::Object^  sender, System::ComponentModel::ProgressChangedEventArgs^  e) {
				 if(e->UserState != "")
				 {
					 array<String^>^ cellValue = e->UserState->ToString()->Split('*');
					resultView->Rows->Add(cellValue[0], cellValue[1]);
				 }
				 progressBar->Value = e->ProgressPercentage;
			 }

	private: System::Void backgroundWorker_RunWorkerCompleted(System::Object^  sender, System::ComponentModel::RunWorkerCompletedEventArgs^  e) {
				buttonCancel->Enabled = false;
				buttonStart->Enabled = true;
			 }
__________________
Blitz3D, XNA, WebGL, OpenGL, Unity3D
PC: ASUS A55VM Core i3 (2.4Ghz), 6 Gb RAM, Nvidia GF 630M GT 2Gb
(Offline)
 
Ответить с цитированием
Старый 26.02.2013, 18:37   #8
pozitiffcat
Мастер
 
Аватар для pozitiffcat
 
Регистрация: 09.05.2010
Адрес: Самара
Сообщений: 1,083
Написано 254 полезных сообщений
(для 533 пользователей)
Ответ: Доступ к GUI с иного потока

.NET CLR зло ИМХО, юзай шарп
(Offline)
 
Ответить с цитированием
Эти 2 пользователя(ей) сказали Спасибо pozitiffcat за это полезное сообщение:
h1dd3n (26.02.2013), ІГРОГРАЙКО (06.03.2013)
Ответ


Опции темы

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

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 04:27.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com