powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / асинхронный запуск функций для DataGridView в Windows Forms
26 сообщений из 26, показаны все 2 страниц
асинхронный запуск функций для DataGridView в Windows Forms
    #38828245
ioscat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Форумчане, прошу вас подсказать, возможно ли асинхронно выполнить некоторую функцию для каждой строки элемента DataGridView? Функция занимает довольно длительное время, причём большая часть уходит на ожидание.
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38828322
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ioscat,

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

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

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

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

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

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

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

1) Visual 2010 C++ Windows Forms

2) Эксепшнов нет, всё работает штатно, вроде бы
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38828374
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Распараллелить то можно.
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38828381
ioscat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
асинхронный запуск функций для DataGridView в Windows Forms
    #38828382
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Твой исходник не является для нас доказательством правильности работы самого процесса
снятия температур. Фиг его знает что у тебя в 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
асинхронный запуск функций для DataGridView в Windows Forms
    #38828402
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ioscatВот это
Код: plaintext
1.
this->BeginInvoke (action, i);


запустит метод в гуевом потоке, в результате чего гуй замёрзнет.
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38828406
ioscat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
асинхронный запуск функций для DataGridView в Windows Forms
    #38828408
ioscat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38829141
ioscat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В алгоритме какой-то косяк?
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38829556
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
асинхронный запуск функций для DataGridView в Windows Forms
    #38829616
ioscat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
petalvik,

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

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

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

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

Код: 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
асинхронный запуск функций для DataGridView в Windows Forms
    #38846631
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ioscat,

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

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

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

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

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

WaitOne используется для того, чтобы после опроса устройств записать информацию из таблицы в лог файл.
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38851917
ioscat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
petalvikМеня шибко интересует, для чего в приведённом коде использовано WaitOne? Ведь это напрочь убивает асинхронность: главный поток приложения будет ожидать, пока завершатся запущенные потоки. Если это нужно, чтобы дождаться результата вычислений, то следует использовать callback, передаваемый в BeginInvoke.
А как дождаться окончания всех потоков, используя callback?
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38852117
petalvik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
асинхронный запуск функций для DataGridView в Windows Forms
    #38852257
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
petalvikуныло писать на C++/CLI
на этом вообще писать нельзя
...
Рейтинг: 0 / 0
асинхронный запуск функций для DataGridView в Windows Forms
    #38870053
Лотсман
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
petalvik,

Чтобы сделать ту же штучку на C# подойдут те .h и .lib файлы, которые используются в C++? Конкретно я имею в виду файлы для создания SNMP запросов.

Код: plaintext
1.
2.
3.
4.
5.
6.
#include <Mgmtapi.h>
#include <Snmp.h>

#pragma comment (lib, "WSNMP32.LIB")
#pragma comment (lib, "Mgmtapi.lib")
#pragma comment (lib, "Snmpapi.lib")    
...
Рейтинг: 0 / 0
26 сообщений из 26, показаны все 2 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / асинхронный запуск функций для DataGridView в Windows Forms
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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