Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.04.2011, 13:44   #1
delias
Пользователь
 
Регистрация: 31.10.2009
Сообщений: 27
По умолчанию Доступ из другого потока Invoke

Ничего не выходит, перепробовал уже всё что только прочитал.
Ситуация такая, в листбокс нужно добоавить текст.
Создал делегата
delegate void AddTextToTListBox(string text);

Далее по наступлении события пытаюсь добавить текст в листбокс:
Код:
void msg_OnSendChatMessage(string message)
        {
            if (listBox1.InvokeRequired)
            {
                AddTextToTextBox d = new AddTextToTextBox(msg_OnSendChatMessage);
                this.Invoke(d, new object[] { message });
                
            }
            else
            {
                listBox1.Text += message + "\r\n";
            }
        }
Но ничего не выходит.
Пробовал вместо AddTextToTextBox d = new AddTextToTextBox(msg_OnSendChatMess age); писать AddTextToTextBox d = new AddTextToTextBox(AddText); а далее
Код:
public void AddText(string text)
        {
            if (this.listBox1.InvokeRequired)
            {
                AddTextToTListBox d = new AddTextToTListBox(AddText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.listBox1.Text = text;
            }
        }
Но тоже самое. И по теме годной статьи тоже не могу найти, в msdn как-то неясно написано совсем.
Буду благодарен за подсказку.
delias вне форума Ответить с цитированием
Старый 06.04.2011, 16:36   #2
Hollander
Участник клуба
 
Аватар для Hollander
 
Регистрация: 03.05.2007
Сообщений: 1,189
По умолчанию

1. Invoke в другом Invoke - плохо. Достаточно Invoke в msg_OnSendChatMessage.
2.
Код:
listBox1.Text = text;
Это что? Чтобы добавить элемент в список надо
Код:
listBox1.Items.Add(text);
3. В чем проявляется Ничего не выходит ?
Hollander вне форума Ответить с цитированием
Старый 07.04.2011, 10:40   #3
delias
Пользователь
 
Регистрация: 31.10.2009
Сообщений: 27
По умолчанию

Цитата:
Сообщение от Hollander Посмотреть сообщение
1. Invoke в другом Invoke - плохо. Достаточно Invoke в msg_OnSendChatMessage.
ок, я и по другому тоже пробовал.
например вот такой вариант:

Код:
        delegate void AddTextToTListBox(string text);

        void msg_OnSendChatMessage(string message)
        {
            
            if (listBox1.InvokeRequired)
            {
                AddTextToTextBox d = new AddTextToTextBox(msg_OnSendChatMessage);
                this.Invoke(d, new object[] { message });
            }
            else
            {
                listBox1.Text += message + "\r\n";
            }  
        }
Цитата:
Сообщение от Hollander Посмотреть сообщение
2.
Код:
listBox1.Text = text;
Это что? Чтобы добавить элемент в список надо
да я просто текст добавляю с разделителями "\r\n"; выходит тоже самое, надеюсь это не грубое нарушение, просто так было быстрее сделать, сейчас проблема как бы не совсем в этом. если это дело не в пототке - то нормально листбокс срабатывает. только в потоке не хочет. хотя это не совсем поток, это сервер и клиент, но видимо листбокс уходит в поток из-за вызванного делегата на клиенте.

Цитата:
Сообщение от Hollander Посмотреть сообщение
3. В чем проявляется Ничего не выходит ?
всё началось с ошибки Cross-thread operation not valid: Control 'listBox1' accessed from a thread other than the thread it was created on.
Сейчас, добавив InvokeRequired, просто виснет программа, не отвечая на запросы. После строки this.Invoke(d, new object[] { message });
delias вне форума Ответить с цитированием
Старый 07.04.2011, 11:10   #4
m0nax
Форумчанин
 
Аватар для m0nax
 
Регистрация: 25.09.2009
Сообщений: 525
По умолчанию

Код:
        void msg_OnSendChatMessage( string message )
        {
            if (listBox1.InvokeRequired)
            {
                Action<string> action = AddToListBox;
                Invoke(action, message);
            }
            else {
                AddToListBox(message);
            }
        }

        void AddToListBox(string msg)
        {
            listBox1.Text += msg + "\r\n";
        }
m0nax вне форума Ответить с цитированием
Старый 07.04.2011, 11:27   #5
delias
Пользователь
 
Регистрация: 31.10.2009
Сообщений: 27
По умолчанию

Цитата:
Сообщение от m0nax Посмотреть сообщение
Код:
        void msg_OnSendChatMessage( string message )
        {
            if (listBox1.InvokeRequired)
            {
                Action<string> action = AddToListBox;
                Invoke(action, message);
            }
            else {
                AddToListBox(message);
            }
        }

        void AddToListBox(string msg)
        {
            listBox1.Text += msg + "\r\n";
        }
Тоже самое, виснет после Invoke(action, message);
попробовал добавить проверку:
Код:
void msg_OnSendChatMessage(string message)
       {
           if (listBox1.InvokeRequired)
           {
               Action<string> action = AddToListBox;
               try
               {
                   Invoke(action, message);
               }
               catch(Exception e)
               {
                   MessageBox.Show(e.ToString());
               }
               
               
           }
           else
           {
               AddToListBox(message);
           }
       }
Но опять безрезультатно, в catch даже не попадает, стопорится на том же месте
delias вне форума Ответить с цитированием
Старый 07.04.2011, 11:29   #6
delias
Пользователь
 
Регистрация: 31.10.2009
Сообщений: 27
По умолчанию

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

п.с. прошу прощения за 2 сообщения подряд - думал оно прикрепится к первому, а удалить не смог
delias вне форума Ответить с цитированием
Старый 07.04.2011, 13:04   #7
Hollander
Участник клуба
 
Аватар для Hollander
 
Регистрация: 03.05.2007
Сообщений: 1,189
По умолчанию

Попробуй через делегат:

Код:
private delegate void AddListBoxItemDelegate(string message);

private void AddListBoxItem(string message)
{
    if (listBox1.InvokeRequired)
    {
        listBox1.Invoke(new AddListBoxItemDelegate(AddListBoxItem), message);
    }
    else
    {
        listBox1.Items.Add(item);
    }
}

void msg_OnSendChatMessage(string message)
{
    AddListBoxItem(message);
}
Hollander вне форума Ответить с цитированием
Старый 07.04.2011, 13:26   #8
delias
Пользователь
 
Регистрация: 31.10.2009
Сообщений: 27
По умолчанию

да не, то же самое.
а у меня вопрос, поставил BeginInvoke вместо Invoke - работает, правда в нужный метод не попадает.
Код:
void msg_OnSendChatMessage(string message)
       {
           if (listBox1.InvokeRequired)
           {
               AddTextToTextBox d = new AddTextToTextBox(AddToListBox);
               this.BeginInvoke(d, new object[] { message });
           }
           else
           {
               listBox1.Text += message + "\r\n";
           }  
       }

       public void AddToListBox(string msg)
       {
           listBox1.Text += msg + "\r\n";
       }
получается проходит this.BeginInvoke(d, new object[] { message }); и потом благополучно возвращается туда, откуда было вызвано это событие
Код:
public void doit(string s)
        {
            OnSendChatMessage(s);
        }
но в AddToListBox не заходит. почему может быть так?
delias вне форума Ответить с цитированием
Старый 07.04.2011, 13:38   #9
Hollander
Участник клуба
 
Аватар для Hollander
 
Регистрация: 03.05.2007
Сообщений: 1,189
По умолчанию

Ждет очереди, мне кажется проблема в потоках. Опиши как они вызываются.
Hollander вне форума Ответить с цитированием
Старый 07.04.2011, 13:57   #10
delias
Пользователь
 
Регистрация: 31.10.2009
Сообщений: 27
По умолчанию

ситуация такая, что я на сервер отправляю строку, и должен постоянно получать CallBack с ответом, чтобы этот ответ вносить в листбокс.
поэтому в классе на сервере есть такой метод:
Код:
public void doit(string s)
        {
            OnSendChatMessage(s);
        }
он передаёт клиенту строку

клиент же её получает при помощи такого делегата:
Код:
CallbackMsg msg = new CallbackMsg();
            msg.OnSendChatMessage += msg_OnSendChatMessage;
            msg.OnSendClientsList += new UserListHandler(msg_OnSendClientsList);
далее при передаче строки наступает собственно то событие, что описано выше, а именно:
Код:
void msg_OnSendChatMessage(string message)
       {
           if (listBox1.InvokeRequired)
           {
               AddTextToTextBox d = new AddTextToTextBox(AddToListBox);
               this.BeginInvoke(d, new object[] { message });
           }
           else
           {
               listBox1.Text += message + "\r\n";
           }  
       }

       public void AddToListBox(string msg)
       {
           listBox1.Text += msg + "\r\n";
       }
т.е. это не совсем как-бы и поток, но если обращаться напрямую к листбоксу без метода Invoke, то получаем эксепшн:
Cross-thread operation not valid: Control 'listBox1' accessed from a thread other than the thread it was created on.

Вот такие пироги.
delias вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка Unable to invoke Code.... sisofcase Общие вопросы Delphi 16 14.07.2011 20:02
Доступ из другого класса KipZ Windows Forms 1 06.02.2011 15:22
Как узнать номер потока из самого потока? GaMeSTeR Помощь студентам 0 03.12.2010 09:50
Доступ к функциям и структурам из потока MAIN_ELF Общие вопросы C/C++ 2 04.10.2010 15:08
директивы в MASM - INVOKE, PROTO, LOCAL fermat_c Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 3 05.04.2008 18:25