Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с многопоточностью, BackgroundWorker() 
:(
    Опции темы
bobadd
Дата 14.11.2007, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 14.11.2007

Репутация: нет
Всего: нет



Проблема следующая. Делаю достаточно большую прогулину, необходимо чтобы на заднем плане в одной из закладок программа считывала данные с COM-порта.
Создал объект         
static BackgroundWorker bw = new BackgroundWorker();

Пока конечно не стал делать считывалку с ком-порта. Пока я убедился в том, что действительно работает на заднем плане второй поток. Но наткнулся на проблему, не могу вернуть данные назад в мою форму.
Т.е. считать то я считаю с com-порта, а чтобы вывести данные, например, в RichTextBox в главной форме... вообщем тут возникла проблема.

Вот примерный код
Код

   public partial class Form1 : Form
    {
        static BackgroundWorker bw = new BackgroundWorker();
...

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {

            //Посылаем объект в другой поток
             bw.RunWorkerCompleted += bw_RunWorkerCompleted;
            bw.DoWork += bw_DoWork;
            bw.RunWorkerAsync(Terminal);   
            //
        }
...

        static void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            // Это будет вызвано рабочим потоком
            while (true) // Данный цикл необходим для постоянной прослушки Com-порта
            {
                System.Threading.Thread.Sleep(2000);
                MessageBox.Show("!!!!!!!!!!!", "Ошибка",   MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }



Вообщем суть проблемы в том, что мне из bw_DoWork нужно как-то добраться до Form1. Собственно говоря, мне нужно добраться до sender'a, насколько я понимаю. Только вот как?
Подскажите пожалуйста
PM MAIL   Вверх
tol05
Дата 14.11.2007, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Не очень понятно что значит "добраться". Если нужен доступ к WinForms контролу (или форме, не важно), то нужно использовать механизм Invoke. Это уже неоднократно обсуждалось... Нужно поиском по сайту пользоваться просто.

для примера, допустим что нужно из bw что-то записывать в 
Цитата(bobadd @  14.11.2007,  17:57 Найти цитируемый пост)
RichTextBox в главной форме

Код

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        static BackgroundWorker bw = new BackgroundWorker();

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            bw.RunWorkerCompleted += bw_RunWorkerCompleted;
            bw.DoWork += bw_DoWork;
            bw.RunWorkerAsync();
        }

        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            bw.Dispose();
        }

        private delegate void RichTextBoxUpdater(string message);


        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            while(true)
            {
                System.Threading.Thread.Sleep(2000);
                richTextBox1.Invoke(new RichTextBoxUpdater(richTextBox1.AppendText), new object[]{"I'm live!\r\n"});
            }
        }
    }




--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
ivashkanet
Дата 14.11.2007, 20:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



tol05, нее, BW настолько грамотный контрол (он действительно контрол, а не просто класс), что никакие инвоки ему не нужны.

У него есть еще несколько событий (кроме DoWork), вот одно из них и позволяет передавать данные из потока "наружу".

Вот тут пример кода работы с Воркером (где-то на форуме была ссылка на неплохую RSDN-овскую статью про него).

Добавлено через 1 минуту и 47 секунд
Нашел: http://www.rsdn.ru/article/dotnet/WinForms20.xml
PM MAIL WWW ICQ   Вверх
tol05
Дата 14.11.2007, 20:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



ну не знаю... я вообще-то принципиальный противник воркера, уже заявлял об этом.. smile
Но вот я убрал Invoke и вот что получил
Код

System.InvalidOperationException was unhandled by user code
  Message="Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on."
  Source="System.Windows.Forms"
  StackTrace:
       at System.Windows.Forms.Control.get_Handle()
       at System.Windows.Forms.TextBoxBase.GetSelectionStartAndLength(Int32& start, Int32& length)
       at System.Windows.Forms.TextBoxBase.AppendText(String text)
       at WindowsApplication4.Form1.bw_DoWork(Object sender, DoWorkEventArgs e) in E:\TempFolder\WindowsApplication2\WindowsApplication4\Form1.cs:line 40
       at System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
       at System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)

код
Код

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            while(true)
            {
                System.Threading.Thread.Sleep(2000);
                richTextBox1.AppendText("I'm live!\r\n");
                //richTextBox1.Invoke(new RichTextBoxUpdater(richTextBox1.AppendText), new object[] { "I'm live!\r\n" });
            }
        }




--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
1stain
Дата 14.11.2007, 20:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 486
Регистрация: 30.7.2007
Где: Киев - Харьков

Репутация: 8
Всего: 40



tol05, потому что DoWork() работает таки в другом потоке, а зато если BW кинет мессадж, а форма его перехватит - то все будет Ок.
Попробуй так:
Код

        public Form1()
        {
            InitializeComponent();

            countBackgroundWorker.RunWorkerAsync(10);
            this.countBackgroundWorker.ProgressChanged += new ProgressChangedEventHandler(countBackgroundWorker_ProgressChanged);
        }

        private void countBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            int countTo = (int)e.Argument;
            for (int i = 1; i <= countTo; ++i)
            {
                countBackgroundWorker.ReportProgress( i*100/countTo, String.Format("i'm {0} miliseconds ago{1}", i*100, Environment.NewLine));
                System.Threading.Thread.Sleep(100);
            }
        }
        private void countBackgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            richTextBox1.AppendText((string)e.UserState);
        }


то есть BW через метод ReportProgress может кинуть форме сообщение, в аргумент которого засунет что захочет, а форма этот мессадж перехватит и обработает...

2ТС: сделай так, чтобы BW читал данные из com, если надо - обрабатывал и через посылал их во 2-м аргументе метода ReportProgress
форма подписывается на событие BW ProgressChanged, приводит ProgressChangedEventArgs.UserState к нужному типу и дальше делай с этими данными на форме что хочешь...

Это сообщение отредактировал(а) 1stain - 14.11.2007, 21:00


--------------------
Все знают, что это невозможно. Но вот приходит невежда, которому это неизвестно - он-то и делает открытие. (Albert Einstein)
user posted image
PM MAIL   Вверх
bobadd
Дата 14.11.2007, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 14.11.2007

Репутация: нет
Всего: нет



Спасибо всем огромное, завтра приду на работу обязательно попробую!
PM MAIL   Вверх
tol05
Дата 14.11.2007, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



1stain, да я как бы знал, что в другом потоке smile 
просто не юзаю ProgressChanged event (потому как я - "старообрядец" )  smile и не люблю ProgressChangedEventHandler.

С воркером не разгуляешься. Приходится за каждым чихом менять код менять то в бизнес-слое, то слое представления... Это плохо... Потому как расчитан он на выполнение отвязанных от слоя представления (UI) узких задач, а для связи - немного в нем заложено... ProgressChanged event да его аргумент. 

Да и вопрос стоял так, чтобы обратиться к контролу из потока воркера. "Обратится" - понятие растяжимое, сегодня значит одно, а завтра может другое. Может завтра данные и не нужно будет передавать, может контролы дизейблить или даже новые создавать завтра нужно будет. К чему тогда ProgressChanged пришивать будем?

Я - сторонник простых потоков и инвоков. 

Это сообщение отредактировал(а) tol05 - 15.11.2007, 02:46


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0449 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.