Можно так использовать DataTable из разных потоков?
От:
Аноним
Дата:
20.08.08 14:32
Оценка:
Привет.
Я создаю форму на которой есть грид.
Грид — это UltraGrid от Infragistics, но думаю это не важно.
Так же создаю DataTable, потом в этом же потоке.
Для грида ставлю DataSource = myDataTable.
Потом создаю другой поток и в другом потоке добавляю строки в этот DataTable. Все операции со строками лочатся примерно так:
lock(myDataTable.Rows.SyncRoot)
{
// добавляю строки
}
Грид обновляет данные, но меня беспокоет является ли такой подход правильным.
Спасибо.
Re: Можно так использовать DataTable из разных потоков?
От:
Аноним
Дата:
22.08.08 07:20
Оценка:
Здравствуйте, Аноним, Вы писали:
А>Привет.
А>Я создаю форму на которой есть грид. А>Грид — это UltraGrid от Infragistics, но думаю это не важно. А>Так же создаю DataTable, потом в этом же потоке. А>Для грида ставлю DataSource = myDataTable.
А>Потом создаю другой поток и в другом потоке добавляю строки в этот DataTable. Все операции со строками лочатся примерно так: А>lock(myDataTable.Rows.SyncRoot) А>{ А>// добавляю строки А>}
А>Грид обновляет данные, но меня беспокоет является ли такой подход правильным.
А>Спасибо.
Не уверен, но скорее нет, чем да.
DataTable не потокобезопасен.
Re: Можно так использовать DataTable из разных потоков?
Изменения всех объектов связанных с интерфейсными правильней всего делать в потоке интерфейсного объекта (хотя исключения наверное есть)
Делал я также, через lock, и было все нормально, пока не написал тестовый генератор таблиц, и столкнулся с иногда выскакивающим эксэпшеном из глубин грида, если в DataTable менялось количество строк
А когда сделал (у меня грид был один, а DataTable'ов много):
// если в другом от грида потоке изменяется таблица которая сейчас отображется, то изменяем ее в потоке гридаif (lastGrid.InvokeRequired && lastGrid.DataSource == dTable) lastGrid.Invoke(delegate () {UpdtForms(...})
// а иначе - просто меняем.else UpdtForms(...
все стало работать стабильно.
Понятно, что раз в потоке грида приходится менять то там нужно минимум работы делать, иначе теряется смысл второго потока.
Re[2]: Можно так использовать DataTable из разных потоков?
От:
Аноним
Дата:
26.08.08 07:38
Оценка:
Здравствуйте, Skynin, Вы писали:
S>Изменения всех объектов связанных с интерфейсными правильней всего делать в потоке интерфейсного объекта (хотя исключения наверное есть)
Да, конечно. Но по идее я не делаю интефейсные изменения (явно), я меняю состояние источника данных и по идее грид должен сам обновляться, что он в принципе и делает. Это не правильный подход?
S>Делал я также, через lock, и было все нормально, пока не написал тестовый генератор таблиц, и столкнулся с иногда выскакивающим эксэпшеном из глубин грида, если в DataTable менялось количество строк
Точь в точь как у меня
S>А когда сделал (у меня грид был один, а DataTable'ов много):
S>
S>// если в другом от грида потоке изменяется таблица которая сейчас отображется, то изменяем ее в потоке грида
S>if (lastGrid.InvokeRequired && lastGrid.DataSource == dTable) lastGrid.Invoke(delegate () {UpdtForms(...})
S>// а иначе - просто меняем.
S>else UpdtForms(...
S>
S>все стало работать стабильно. S>Понятно, что раз в потоке грида приходится менять то там нужно минимум работы делать, иначе теряется смысл второго потока.
Мне к сожалению это не подходит. У меня строки в DataTable добавляются весьма активно и постоянное обновления DataSource у грида привидёт к его постоянной перерисовке.
Есть ещё идеи?
Спасибо за ответ, кстати , а то помощи как-то не много...
Re[3]: Можно так использовать DataTable из разных потоков?
А>Да, конечно. Но по идее я не делаю интефейсные изменения (явно), я меняю состояние источника данных и по идее грид должен сам обновляться, что он в принципе и делает. Это не правильный подход?
Он сам и обновляется. В потоке в котором меняется состояние источника данных.
Правильный ли подход что Windows Forms реализован нереентабельным кодом?
По моему да. Опуская аргументы о быстродействии, а сугубо философски — а зачем GUI многозадачность?
Но главное — убедят ли аргументы о неправильности — авторов Windows Forms?
А>Мне к сожалению это не подходит. У меня строки в DataTable добавляются весьма активно и постоянное обновления DataSource у грида привидёт к его постоянной перерисовке. А>Есть ещё идеи?
Последняя мера — готовить отдельную DataTable, а потоке грида оставить только — .DataSource = dTable;
Или написать свой грид.
Re[4]: Можно так использовать DataTable из разных потоков?
От:
Аноним
Дата:
27.08.08 08:05
Оценка:
Здравствуйте, Skynin, Вы писали:
S>Он сам и обновляется. В потоке в котором меняется состояние источника данных.
Блин,блин, блин!!! Чтоб не сказать больше!! Я об этом не подумал.
Конечно, тогда всё становится логичным: обращаемся из другого потока к контролу — имеем проблемы.
Спасибо
Я-то думал, что имею проблемы с использованием DataTable из разных потоков, а оказывается юзаю (косвенно как бы) контрол из разных потоков.
Теперь уже подумаю как перестроить код с учётом этого нюанса
S>Последняя мера — готовить отдельную DataTable, а потоке грида оставить только — .DataSource = dTable;
Хм... А можно с этого места поподробнее? Отдельную DataTable для чего?
В потоке грида я и так создаю свой DataTable и устанавливаю .DataSource = dTable, а заполняю dTable в фоновом потоке.
S>Или написать свой грид.
Бррр... Не могу позволить себе убить кучу времени
Ещё раз спасибо!
Re[5]: Можно так использовать DataTable из разных потоков?
А>Я-то думал, что имею проблемы с использованием DataTable из разных потоков, а оказывается юзаю (косвенно как бы) контрол из разных потоков.
Именно. Не исследовал, но наверняка при присвоении .DataSource = dTable грид цепляется на события DataTable. Тот их конечно генерит, при изменении. Но в потоке изменений. И в этом же потоке грид получает событие и обрабатывает.
А>Теперь уже подумаю как перестроить код с учётом этого нюанса А>В потоке грида я и так создаю свой DataTable и устанавливаю .DataSource = dTable, а заполняю dTable в фоновом потоке.
Так это и есть — неправильно! Если с гридом связан DataTable, то его нельзя изменять в другом потоке! Выше Вы вроде как поняли, а теперь опять: заполняю dTable в фоновом потоке
Вариант о котором я говорил — другой.
Поток А
...в нем живет грид
Поток B
... dTable = new DataTable
.. и т.д.
Invoke // переключаемся в Поток А
.DataSource = dTable
А если:
Поток А
...в нем живет грид
dTable = new DataTable
.DataSource = dTable
Поток B, запускаем после присвоения .DataSource = dTable
изменяем dTable, при этом грид обратывает события DataTable.
то и будет — горе.
Re[6]: Можно так использовать DataTable из разных потоков?
От:
Аноним
Дата:
29.08.08 07:21
Оценка:
Здравствуйте, Skynin, Вы писали:
А>>В потоке грида я и так создаю свой DataTable и устанавливаю .DataSource = dTable, а заполняю dTable в фоновом потоке. S>Так это и есть — неправильно! Если с гридом связан DataTable, то его нельзя изменять в другом потоке! Выше Вы вроде как поняли, а теперь опять: заполняю dTable в фоновом потоке
Понял, понял
Я подумал, что это была попытка озвучить идею, как нужно поступить.
S>Вариант о котором я говорил — другой.
S>Поток А S>...в нем живет грид S>Поток B S>... dTable = new DataTable S>.. и т.д. S>Invoke // переключаемся в Поток А S>.DataSource = dTable