Текстовое поле 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, должны обрабатываться соответствующим образом, иначе вы выбросите исключения потока пользовательского интерфейса.