четверг, 15 декабря 2011 г.

(1) Из потока в поток ...

Уважаемые коллеги !

Сегодня мне хотелось бы коснуться одной проблемы, связанной с использованием контрола BackGroundWorker. Судя по всему, эта проблема многим потрепала нервы и во многом снизила интерес к использованию этого замечательного контрола - а это, в общем-то, никто и не оспаривает.

Несмотря на то, что я не супер-пупер в программировании, меня задел тот факт, что практически никто (а я обошел почти весь Рунет, американские поисковики, а также провел выборочный поиск по немецким и французским сайтам) не смог решить задачу передачи данных из одного потока в другой (основной) с использованием BackGroundWorker.

Короче, постараюсь продемонстрировать суть проблемы на примере и в двух словах дать общее направление решения.

Где-то в начале весны пришла мне в голову мысль подправить собственную программу для домашнего использования под названием Electra (как в драме Еврипида). Вообще-то она предназначена для экономии электроэнергии. При этом мне потребовалось добавить отдельную форму для поиска файлов на диске. Сам код поиска я сунул в .dll-файл. Тут никаких видимых проблем не возникло. Поиск работал, как по маслу.

Но пока мой поисковик что-то искал, все остальное, естественно, резко зависало. После некоторых мытарств я решил попробовать контрол BackGroundWorker. В целом с ним тоже никаких проблем не возникло: всего-то несколько совершенно очевидных процедур.

От использования Progressbar (только в рамках процедур BackGroundWorker) пришлось отказаться, поскольку он считает от 1% до 100% (не буду останавливаться, поскольку спецы понимают, о чем речь). Progressbar, конечно, есть на форме, но он ничего не считает, а, собственно говоря, лишь показывает юзеру, что какойто процесс все-таки идет..

Итак, о главном. Задача стояла в том, чтобы найденные файлы последовательно (!!!) вставлялись в DataGridView. Но этого, конечно, не удалось. BackGroundWorker меня вежливо предупредил: "Недопустимая операция в нескольких потоках: попытка доступа к элементу управления 'TextBox1' не из того потока, в котором он был создан". Ежу понятно, что при использовании BackGroundWorker доступ к контролам основного потока невозможен. Конечно, его легко можно организовать, используя обработчик события ProgressChanged (впрочем, как и переменные приложения, что нежелательно при допущении параллельного доступа к ним). Но это меня, как и многих других, мало заинтересовало, поскольку задачи стояли несколько иные.

Ну, конечно, я полазил в MSDN, походил по форумам. Пытался использовать таймеры, массивы и еще что-то. Но это все изврат. При этом реальной последовательной вставки найденных файлов в DataGridView мне достичь не удалось.

В конце-концов пришлось прибегнуть к старому испытанному методу - ВСПОМНИТЬ !!!  Ведь что-то похожее когда-то уже было. И не стоит изобретать велосипед.

Выпив чашечку кофе, покурив пару сигарет, я вспомнил. Лет 8-10 тому назад на одном из форумов одна девушка (она, кажется, ни одного форума не пропустила) что-то кому-то разъясняла. И она привела примерно следующую фразу: У каждого окна (Window) есть своя ручка (Handle).

Другими словами, задача в целом решена. Для этого тупо используем стандартную функцию SendMessage и элементарно кидаем найденные файлы в текстбоксы. Козе понятно, что без AddHandler не обойтись. Но это уже частности.

Уверен, что продвинутые программисты суть сразу же усекли и побежали вносить изменения в свои программы. Как говорится, флаг в руки ! Успехов !

Для особо ленивых, непонятливых или недостаточно опытных не сегодня-завтра выложу готовую программу (конечно, нескомпилированную). Сегодня - не уверен, сейчас должен прийти сборщик мебели, и мне придется на некоторое время оторваться от любимого занятия.
За это приношу всему сообществу мои извинения.

А пока - выкладываю скриншот.


Комментариев нет: