DataAdapter.Fill(datatable) в отдельном потоке
От: tnikolai  
Дата: 24.09.06 10:19
Оценка:
Если вызываю DataAdapter.Fill(datatable) в отдельном потоке, то в связанной через BindingSource сетке ничего не отображается.
Однако обнаружил, что если просто щёлкнуть на к-л заголовке столбца в сетке, данные появляются. Но как это сделать програмно? Пытался в конце вызывать Refresh, update, ResumeBinding, ResetBinding, а так же заключать вызов в beginInit, suspendBinding, suspendLayout — ничего не помогает, сетка полюбому пустая.

А всё это мне нужно только для того, чтоб показать Progress bar при ыполнении длительного запроса. Нужно чтоб Progress bar просто крутился не отражая реальный % выполнения запроса. Progress bar приходится выполнять в основном потоке(по таймеру через Invoke), иначе появляется ошибка InvalidOperationException.
Если DataAdapter.Fill(datatable) выполняю в основном потоке, то он его полностью занимает и пока не выполнится, прогресс не идёт.
В общем что ни пытюсь сделать — натыкаюсь на непреодолимый тупик.

Неужели такую простую вещь как Progress bar невозможно сделать?
Re: DataAdapter.Fill(datatable) в отдельном потоке
От: Igor Trofimov  
Дата: 24.09.06 16:34
Оценка:
T>Если DataAdapter.Fill(datatable) выполняю в основном потоке, то он его полностью занимает и пока не выполнится, прогресс не идёт.

Дело видимо, в том, что если вы делаете Fill в параллельном потоке, то и события для обновления прибинденных контролов расходятся синхронно в параллельном потоке. Это вообще плохо.

T>В общем что ни пытюсь сделать — натыкаюсь на непреодолимый тупик.

T>Неужели такую простую вещь как Progress bar невозможно сделать?

Попробуйте делать в параллельном потоке Fill в отсоединенный от контролов DataSet, а потом в основном потоке подключать его к гриду или куда там вы его подключаете.
Re[2]: DataAdapter.Fill(datatable) в отдельном потоке
От: tnikolai  
Дата: 25.09.06 06:57
Оценка:
iT>Попробуйте делать в параллельном потоке Fill в отсоединенный от контролов DataSet, а потом в основном потоке подключать его к гриду или куда там вы его подключаете.

В BindingSource перед этим зануляю DataSource, DataMember; выполняю Fill в другом потоке, возвращаю DataSource, DataMember в исходное значение.
Не помогает — та же самая ситуация.
Может этими компонентами можно работать лишь в том потоке, в котором они созданы?
Если это так, то progress bar сделать поистине невозможно.
Re[3]: DataAdapter.Fill(datatable) в отдельном потоке
От: shelkovnikov Россия  
Дата: 25.09.06 07:21
Оценка:
Здравствуйте, tnikolai, Вы писали:

iT>>Попробуйте делать в параллельном потоке Fill в отсоединенный от контролов DataSet, а потом в основном потоке подключать его к гриду или куда там вы его подключаете.


T>В BindingSource перед этим зануляю DataSource, DataMember; выполняю Fill в другом потоке, возвращаю DataSource, DataMember в исходное значение.

T>Не помогает — та же самая ситуация.
T>Может этими компонентами можно работать лишь в том потоке, в котором они созданы?
T>Если это так, то progress bar сделать поистине невозможно.

Попробуйте основной поток приложения сделать MTA, форму открывать в STA (иначе половина COM объектов не работает)
Почему? STA создается один на приложение (как скрытое окно) и все потоки с этим атрибутом синхронизуются через общую оконную функцию: нормального паралелизма нет.
Re[4]: DataAdapter.Fill(datatable) в отдельном потоке
От: tnikolai  
Дата: 25.09.06 08:27
Оценка:
Здравствуйте, shelkovnikov, Вы писали:

S>Попробуйте основной поток приложения сделать MTA, форму открывать в STA (иначе половина COM объектов не работает)

А как это сделать? Вообщето я COM вообще не использую, и подобное делать нежелательно.

S>Почему? STA создается один на приложение (как скрытое окно) и все потоки с этим атрибутом синхронизуются через общую оконную функцию: нормального паралелизма нет.

Если нормального параллелизма нет, то DataAdapter.Fill может и выполнится нормально, но пока он не закончит выполнение, progress bar не сдвинется с места.
Re[3]: DataAdapter.Fill(datatable) в отдельном потоке
От: Igor Trofimov  
Дата: 25.09.06 10:51
Оценка:
T>В BindingSource перед этим зануляю DataSource, DataMember; выполняю Fill в другом потоке, возвращаю DataSource, DataMember в исходное значение.

Возвращаешь — в каком потоке?

T>Может этими компонентами можно работать лишь в том потоке, в котором они созданы?


Со всеми контролами надо работать из того потока, где они были созданы, т.е. обычно — из главного потока приложения.

С DataDet, DataAdapter, etc — в любых потоках.
Re[4]: DataAdapter.Fill(datatable) в отдельном потоке
От: tnikolai  
Дата: 25.09.06 11:41
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>Возвращаешь — в каком потоке?

Всё в основном. Только Fill в другом потоке выполняетя.

iT>Со всеми контролами надо работать из того потока, где они были созданы, т.е. обычно — из главного потока приложения.

iT>С DataDet, DataAdapter, etc — в любых потоках.
Только с DataDet. В справке для DataAdapter сказано, что только public static члены потокобезопасны, а для остальных не гарантируется потокобезопасность.
Re[5]: DataAdapter.Fill(datatable) в отдельном потоке
От: Igor Trofimov  
Дата: 25.09.06 12:01
Оценка:
iT>>Возвращаешь — в каком потоке?
T>Всё в основном. Только Fill в другом потоке выполняетя.

Ну тогда должно работать


iT>>Со всеми контролами надо работать из того потока, где они были созданы, т.е. обычно — из главного потока приложения.

iT>>С DataDet, DataAdapter, etc — в любых потоках.
T>Только с DataDet. В справке для DataAdapter сказано, что только public static члены потокобезопасны, а для остальных не гарантируется потокобезопасность.

А я не говорил про потокобезопасность в том смысле, что параллельно из нескольких потоков можно работать.
Я говорил про то, что можно работать из любого потока. Контролы имеют привязку к потоку. DataSet, DataAdapter — нет.
Re[6]: DataAdapter.Fill(datatable) в отдельном потоке
От: Igor Trofimov  
Дата: 25.09.06 12:22
Оценка:
Еще один момент. В основном потоке, чтобы не замораживался интерфейс, нужно либо вызывать Application.DoEvents, либо не держать выполнение.

Если тебе надо управлять ProgressBar'ом, пока не закончилось выполнение потока с Fill, то либо цикл управления ProgressBar'ом выноси в еще один поток, либо внутрь этого ожидающего цикла вставь Application.DoEvents.
Re[6]: DataAdapter.Fill(datatable) в отдельном потоке
От: tnikolai  
Дата: 25.09.06 13:53
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>>>Возвращаешь — в каком потоке?

T>>Всё в основном. Только Fill в другом потоке выполняетя.

iT>Ну тогда должно работать

Работает, но с глюком(сетка пустая пока не щёлкнеш на заголовок столбца), видимо из-за того, что DataAdapter не потокобезопасен.


iT>>>Со всеми контролами надо работать из того потока, где они были созданы, т.е. обычно — из главного потока приложения.

iT>>>С DataDet, DataAdapter, etc — в любых потоках.
T>>Только с DataDet. В справке для DataAdapter сказано, что только public static члены потокобезопасны, а для остальных не гарантируется потокобезопасность.

iT>А я не говорил про потокобезопасность в том смысле, что параллельно из нескольких потоков можно работать.

iT>Я говорил про то, что можно работать из любого потока. Контролы имеют привязку к потоку. DataSet, DataAdapter — нет.

В любом смысле с непотокобезопасным номпонентом в другом потоке работать нельзя, даже и из одного потока!
Re[7]: DataAdapter.Fill(datatable) в отдельном потоке
От: Igor Trofimov  
Дата: 25.09.06 13:59
Оценка:
T>Работает, но с глюком(сетка пустая пока не щёлкнеш на заголовок столбца), видимо из-за того, что DataAdapter не потокобезопасен.

Ерунда какая-то. Давай код, посмотрим.

T>В любом смысле с непотокобезопасным номпонентом в другом потоке работать нельзя, даже и из одного потока!


А что такое "другой" поток, по-твоему? "Другой" по отношению к чему?
Re[7]: DataAdapter.Fill(datatable) в отдельном потоке
От: tnikolai  
Дата: 25.09.06 14:35
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>Еще один момент. В основном потоке, чтобы не замораживался интерфейс, нужно либо вызывать Application.DoEvents, либо не держать выполнение.


Если бы DataAdapter.Fill можно было бы прерывать вызовами Application.DoEvents! Проблемм бы не было.

iT>Если тебе надо управлять ProgressBar'ом, пока не закончилось выполнение потока с Fill, то либо цикл управления ProgressBar'ом выноси в еще один поток, либо внутрь этого ожидающего цикла вставь Application.DoEvents.


А вот вынести ProgressBar.PerfomStep в отдельный поток никак не получается. Требует выполнения только в основном потоке, или выдаёт ошибку InvalidOperationException. Если использовать Invoke/BeginInvoke, то пока DataAdapter.Fill занимает поток, ProgressBar с места не двигается.
Re[8]: DataAdapter.Fill(datatable) в отдельном потоке
От: tnikolai  
Дата: 25.09.06 14:38
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

T>>В любом смысле с непотокобезопасным номпонентом в другом потоке работать нельзя, даже и из одного потока!


iT> А что такое "другой" поток, по-твоему? "Другой" по отношению к чему?

Не тот, в котором компонент создан.
Re[9]: DataAdapter.Fill(datatable) в отдельном потоке
От: Igor Trofimov  
Дата: 25.09.06 15:34
Оценка:
T>>>В любом смысле с непотокобезопасным номпонентом в другом потоке работать нельзя, даже и из одного потока!
iT>> А что такое "другой" поток, по-твоему? "Другой" по отношению к чему?
T>Не тот, в котором компонент создан.

И где, по-твоему, DataAdapter связывается с потоком, в котором он был создан?
Или скажем, ArrayList? Он по-дефолту тоже "не потокобезопасен".
Re[8]: DataAdapter.Fill(datatable) в отдельном потоке
От: Igor Trofimov  
Дата: 25.09.06 15:38
Оценка: 3 (1)
Короче, я тут накидал тебе простой пример.
Вместо адаптера и базы данных там просто генератор данных для таблицы.
Но не думаю, что с DataAdapter'ом что-то изменится и перестанет работать.

TestThreadFill.zip
Re[9]: DataAdapter.Fill(datatable) в отдельном потоке
От: tnikolai  
Дата: 25.09.06 18:57
Оценка:
Здравствуйте, Igor Trofimov, Вы писали:

iT>Короче, я тут накидал тебе простой пример.

iT>Вместо адаптера и базы данных там просто генератор данных для таблицы.
iT>Но не думаю, что с DataAdapter'ом что-то изменится и перестанет работать.

iT>TestThreadFill.zip


Всё получилось!
Спасибо!
У меня была дурацкая ошибка.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.