Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / асинхронный запуск функций для DataGridView в Windows Forms / 25 сообщений из 26, страница 1 из 2
08.12.2014, 16:48
    #38828245
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
Форумчане, прошу вас подсказать, возможно ли асинхронно выполнить некоторую функцию для каждой строки элемента DataGridView? Функция занимает довольно длительное время, причём большая часть уходит на ожидание.
...
Рейтинг: 0 / 0
08.12.2014, 18:17
    #38828322
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
ioscat,

какой источник данных у DataGridView? Или строки заполнены вручную?
Нужно лишь читать данные из DataGridView или менять тоже?
...
Рейтинг: 0 / 0
08.12.2014, 18:27
    #38828331
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
petalvik,

Вручную заполняется один столбец - IP адрес, как вариант просто читается файлик, в котором с новой строки адреса написаны, но это уже сделано, и работает хорошо работает по кнопке.

В функцию передаётся значения поля строки DataGridView, функция возвращает температуру устройства, которая заносится в специальный столбец. Беда в том, что запрос идёт несколько секунд, и опрос сотни устройств выливается в несколько минут.

Поэтому я попытался запускать поток для каждой строки через BeginInvoke, но, видимо, это всё же не то, что нужно.
...
Рейтинг: 0 / 0
08.12.2014, 19:20
    #38828365
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
Если тот источник данных который тащит температуру может обрабатывать групповые запросы
то его нужно озадачить выборкой не 1 запроса а сразу десятка или сотни. И делать это
предварительно. До того как пользователь открыл грид. И кешировать по возможности.
...
Рейтинг: 0 / 0
08.12.2014, 19:24
    #38828368
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
Мне кажется, вы меня не понимаете. Источника данных в виде базы нет. Есть программка, которая посылает запросы SNMP к устройствам по списку IP адресов, занесённых в DataGridView. На текущий момент программа делает запросы последовательно: послали первому, ждём ответ, заносим в таблицу, повторить. Можно ли распараллелить процесс опроса устройств, запуская функцию опроса для каждой строки DataGridView в отдельных потоках?
...
Рейтинг: 0 / 0
08.12.2014, 19:24
    #38828369
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
ioscat,

работать нужно не с датагридом, а с источником данных. Этим источником может быть DataTable, List<T> или другая коллекция. А этот источник привязывается к датагриду.

Так а что не так с BeginInvoke? Вероятно, вылетает эксепшен - доступ к гую из другого потока? Отсюда и следует желательность работы с привязанным источником данных.

Язык C++/CLI? Или случайно не в тот раздел?
...
Рейтинг: 0 / 0
08.12.2014, 19:26
    #38828371
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
petalvik,

1) Visual 2010 C++ Windows Forms

2) Эксепшнов нет, всё работает штатно, вроде бы
...
Рейтинг: 0 / 0
08.12.2014, 19:37
    #38828374
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
Распараллелить то можно.
...
Рейтинг: 0 / 0
08.12.2014, 19:58
    #38828381
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
mayton,

Что-то не так? =)

Я использовал следующий код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
delegate void CheckStringDelegate(int i);

void CheckString(int i)
{
    //Do smth with i row from DataGridView
}

private: System::Void ChBut_Click(System::Object^  sender, System::EventArgs^  e) 
{
	//CheckOperation();
	for (int i=0; i<(dataGridView1->RowCount);i++) 
	{
		//IAsyncResult ^ caller = ChBut->BeginInvoke(gcnew CheckStringDelegate(this, &Form1::CheckString), i);
		CheckStringDelegate ^ action = gcnew CheckStringDelegate(this, &Form1::CheckString);
		this->BeginInvoke (action, i);
	}
}
...
Рейтинг: 0 / 0
08.12.2014, 20:02
    #38828382
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
Твой исходник не является для нас доказательством правильности работы самого процесса
снятия температур. Фиг его знает что у тебя в runtime творится.

Сделай так.
Код: plaintext
1.
2.
3.
4.
5.
6.
void CheckString(int i)
{
    printf("Begin processing %i\n",i);
    //Do smth with i row from DataGridView
    printf("End processing %i\n",i);
}


И покажи вывод.
...
Рейтинг: 0 / 0
08.12.2014, 20:18
    #38828402
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
ioscatВот это
Код: plaintext
1.
this->BeginInvoke (action, i);


запустит метод в гуевом потоке, в результате чего гуй замёрзнет.
...
Рейтинг: 0 / 0
08.12.2014, 20:23
    #38828406
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
mayton,

Я немного отклонился от вашего кода, использовал такой:
Код: plaintext
1.
2.
3.
4.
5.
void CheckString(int i)
{
	System::Diagnostics::Trace::WriteLine("Start processung");
	System::Diagnostics::Trace::WriteLine("End processung");
}



Вывод:
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
Start processung
End processung
...
Рейтинг: 0 / 0
08.12.2014, 20:26
    #38828408
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
...
Рейтинг: 0 / 0
09.12.2014, 15:57
    #38829141
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
В алгоритме какой-то косяк?
...
Рейтинг: 0 / 0
09.12.2014, 20:52
    #38829556
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
ioscat,

метод Control::BeginInvoke выполняет код в потоке, создавшем контрол. То есть в GUI-потоке. Поэтому в данном случае выполнение получится однопоточное и к тому же пока код выполняется, GUI не будет перерисовываться (замёрзнет).

Нужно вызывать BeginInvoke на самом делегате:
Код: plaintext
1.
2.
CheckStringDelegate ^ action = gcnew CheckStringDelegate(this, &Form1::CheckString);
action->BeginInvoke(i, nullptr, nullptr);



А если в методе CheckString происходит изменение gui-контролов, вот тогда нужно использовать Control::BeginInvoke, иначе будет исключение.
...
Рейтинг: 0 / 0
09.12.2014, 22:39
    #38829616
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
petalvik,

вроде сработало... завтра проверю в деле...
спасибо большое!
...
Рейтинг: 0 / 0
10.12.2014, 09:34
    #38829832
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
petalvik, спасибо, работает.

Можете посоветовать, где про это можно прочитать?
Предложения РЗФМ подходят, когда уже хорошо ориентируешься и самостоятельно можешь оценить полезность материала, и ещё больше, если ищешь что-то конкретное.
...
Рейтинг: 0 / 0
10.12.2014, 16:50
    #38830466
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
ioscat,

я не сразу сообразил, что такое РЗФМ.
Читать, наверное, следует Асинхронная модель программирования .
Боюсь что не все примеры кода есть на C++. Для .NET и WinForms лучше использовать C#.
...
Рейтинг: 0 / 0
30.12.2014, 10:55
    #38846322
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
Снова всем привет!

А такие потоки как в моём примере после завершения отдают память системе автоматически?

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
	delegate void CheckStringDelegate(int i);

	void CheckString(int i)
	{
		//do smth with i-row of the DataGridView
	}

	void UpdateDeviceTable()
	{
		array <IAsyncResult^> ^ res = gcnew array <IAsyncResult^> (DevicesTable->RowCount) ;
		CheckStringDelegate ^ action;
			
		for (int i=0;i<DevicesTable->RowCount;i++)
		{
			action = gcnew CheckStringDelegate(this, &Form1::CheckString);
			res [i]= action->BeginInvoke (i, nullptr, nullptr );
		}
					
		for(int i=0;i<DevicesTable->RowCount;i++)
		{
			res[i]->AsyncWaitHandle->WaitOne();
		}
			
		auto MyWriter = gcnew IO::StreamWriter(TempDescrTextBox->Text, true, System::Text::Encoding::GetEncoding(1251));
	} 
...
Рейтинг: 0 / 0
30.12.2014, 15:25
    #38846631
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
ioscat,

BeginInvoke берёт потоки из пула. После завершения работы потоки вернутся в пул.

Однако, шаблон APM предполагает, что после завершения работы потока результат из него будет как-то использоваться, через IAsyncResult. В приведённом коде я этого не вижу.
Меж тем, запуск потока через BeginInvoke несёт некоторый оверхед. Если нужно просто fire and forget (запустил и забыл), то лучше работать напрямую с пулом: ThreadPool::QueueUserWorkItem.

Меня шибко интересует, для чего в приведённом коде использовано WaitOne? Ведь это напрочь убивает асинхронность: главный поток приложения будет ожидать, пока завершатся запущенные потоки. Если это нужно, чтобы дождаться результата вычислений, то следует использовать callback, передаваемый в BeginInvoke.

Сколько всего строк в датагриде? Хотя бы примерно: десятки, сотни, тысячи?
...
Рейтинг: 0 / 0
30.12.2014, 19:25
    #38846837
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
petalvik,

Десятки. Максимум полторы сотни. Теоретический предел 10 тысяч, но этого не будет.
...
Рейтинг: 0 / 0
30.12.2014, 19:26
    #38846839
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
ioscat,

WaitOne используется для того, чтобы после опроса устройств записать информацию из таблицы в лог файл.
...
Рейтинг: 0 / 0
12.01.2015, 09:30
    #38851917
ioscat
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
petalvikМеня шибко интересует, для чего в приведённом коде использовано WaitOne? Ведь это напрочь убивает асинхронность: главный поток приложения будет ожидать, пока завершатся запущенные потоки. Если это нужно, чтобы дождаться результата вычислений, то следует использовать callback, передаваемый в BeginInvoke.
А как дождаться окончания всех потоков, используя callback?
...
Рейтинг: 0 / 0
12.01.2015, 12:23
    #38852117
petalvik
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
ioscatWaitOne используется для того, чтобы после опроса устройств записать информацию из таблицы в лог файл.
ioscatА как дождаться окончания всех потоков, используя callback?

Если информацию можно записывать в файл по одной строке, независимо от остальных, причём порядок их неважен (т. к. вызовы BeignInvoke будут срабатывать в произвольном порядке) то это можно делать в колбэке.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
void UpdateDeviceTable()
{
	array <IAsyncResult^> ^res = gcnew array <IAsyncResult^>(DevicesTable->RowCount);
	CheckStringDelegate ^action;

	for (int i = 0; i < DevicesTable->RowCount; i++)
	{
		action = gcnew CheckStringDelegate(this, &Form1::CheckString);
		res[i] = action->BeginInvoke(i, gcnew AsyncCallback(this, &Form1::myCallback), i);
	}
}

void myCallback(IAsyncResult ^ar)
{
	int index = (int)ar->AsyncState;
	Console::WriteLine(index); // тут пишем в файл информацию об одной строке
}



Если обязательно нужно дождаться выполнения всех опросов и/или важен порядок записи, тогда придётся дожидаться окончания всех потоков. А чтобы пользовательский интерфейс не замерзал на это время, сам метод UpdateDeviceTable нужно запускать асинхронно (в другом потоке). Что-то вроде:
Код: plaintext
1.
ThreadPool::QueueUserWorkItem(gcnew WaitCallback(this, &Form1::UpdateDeviceTable));


Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
void UpdateDeviceTable(Object ^state)
{
	array <IAsyncResult^> ^res = gcnew array <IAsyncResult^>(DevicesTable->RowCount);
	CheckStringDelegate ^action;

	for (int i = 0; i < DevicesTable->RowCount; i++)
	{
		action = gcnew CheckStringDelegate(this, &Form1::CheckString);
		res[i] = action->BeginInvoke(i, nullptr, nullptr);
	}

	for (int i = 0; i<DevicesTable->RowCount; i++)
	{
		res[i]->AsyncWaitHandle->WaitOne();
	}

	Console::WriteLine("test"); // тут пишем в файл сразу всё
}



PS: как всё-таки уныло писать на C++/CLI после C#. Интеллисенс ни к чёрту, много лишней писанины и пр.
...
Рейтинг: 0 / 0
12.01.2015, 14:25
    #38852257
Изопропил
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
асинхронный запуск функций для DataGridView в Windows Forms
petalvikуныло писать на C++/CLI
на этом вообще писать нельзя
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / асинхронный запуск функций для DataGridView в Windows Forms / 25 сообщений из 26, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]