Можно так использовать 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 из разных потоков?
От: Skynin Украина skynin.blogspot.com
Дата: 24.08.08 09:04
Оценка:
Изменения всех объектов связанных с интерфейсными правильней всего делать в потоке интерфейсного объекта (хотя исключения наверное есть)

Делал я также, через 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 из разных потоков?
От: Skynin Украина skynin.blogspot.com
Дата: 26.08.08 20:06
Оценка: 2 (1)
А>Да, конечно. Но по идее я не делаю интефейсные изменения (явно), я меняю состояние источника данных и по идее грид должен сам обновляться, что он в принципе и делает. Это не правильный подход?
Он сам и обновляется. В потоке в котором меняется состояние источника данных.
Правильный ли подход что 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 из разных потоков?
От: Skynin Украина skynin.blogspot.com
Дата: 28.08.08 12:47
Оценка: 1 (1)
А>Я-то думал, что имею проблемы с использованием 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

Уже примерно так и сделал.
Спасибо.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.