Текстовое поле C# не обновляется при использовании с SocketIO4NET


У меня странная проблема. Я использую SocketIO4Net Client для моей программы, написанной на C#. Программа связывается с сервером, написанным на NodeJS & SocketIO. Я могу отправлять и получать данные между моей программой и сервером, используя методы socket.emit() и socket.On() в клиенте SocketIO4NET. Однако, когда я пытаюсь обновить текстовое поле в графическом интерфейсе с данными, которые я получил от сервера, ничего не происходит. Но, если я использую метод MessageBox.Show(), я могу отобразить полученные данные. Я использую следующий код для получения данных:

public Form1()
    {
        InitializeComponent();
        socket = new Client("http://127.0.0.1:80/");
        socket.On("message", (data) =>
        {
             String msg = data.Json.Args[0].ToString();
             MessageBox.Show(msg,"Received Data");
             rxtxtbox.Text = msg;


        });
        socket.Connect();
    }

Для отправки данных:

 private void sendbtn_Click(object sender, EventArgs e)
    {
        String msg = msgtxtbox.Text.ToString();
        socket.Emit("private message", msg);
    }

Приведенный выше код работает нормально. Но это не обновление TextBox 'rxtxtbox'. Если я переместить строку "rxtxtbox.Text = msg;" выше "MessageBox.Show();", то при получении события "message" ничего не произойдет. Я попытался установить точки останова и посмотреть значение переменной "msg" и это нормально. Я попытался объявить другую функцию, просто чтобы обновить текстовое поле и передать ему сообщение "msg", но все еще не получил результатов! Я думаю, это как-то связано с ожиданием события "сообщение"? Я попробовал методы "Application.DoEvents()" и "rxtxtbox.Refresh()" и все еще не повезло! Я новичок в C#. Пожалуйста помоги!

1 ответ

Решение

Вы упоминаете, что если вы поместите MessageBox.Show перед rxtxtbox.Text - вы увидите данные полезной нагрузки, но сначала будет rxtxtbox.Text - ничего не произойдет.

Обработчики событий из socketIO4Net определенно работают в фоновом потоке, поэтому я готов поспорить, что вы выдаете исключение, обновляющее элемент управления пользовательского интерфейса - из этого потока без пользовательского интерфейса. Насколько я понимаю, MessageBox не связан с пользовательским интерфейсом, поэтому его можно вызывать из не-пользовательских потоков без проблем.

Попробуйте это вместо строки rxtxtbox.Text = msg:

rxtxtbox.Invoke(new Action(() => rxtxtbox.Text = msg)));

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

Вы также можете поместить эту строку непосредственно перед обновлением свойства Text и проверить его (если true, вы действительно не в пользовательском потоке и обнаружили свою проблему):

bool state = rxtxtbox.InvokeRequired;

Существуют различные способы обработки обновлений графического интерфейса из не-пользовательских потоков. Поиск многопоточности Winforms GUI C# и т. Д. Здесь, на SO. Любые сообщения, полученные от socketio4net, должны обрабатываться соответствующим образом, иначе вы выбросите исключения потока пользовательского интерфейса.

Другие вопросы по тегам