Не удается изменить текст текстового поля

#c# #winforms

Вопрос:

Я хотел бы изменить текст текстового поля в моем Backgroundworker, но это не работает, и я не могу найти ошибку в своем коде.

Фоновый работник:

 class Check_Server
{
    WebSocket webSocket = new WebSocket("ws://localhost:8548");
    private Form1 Form1;

    public void Check_WebSocket(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;
        while (!worker.CancellationPending)
        {
            Console.WriteLine("checking connection");
            if (webSocket.IsAlive == true)
            {
                Console.WriteLine("connected");
            }
            else
            {
                Console.WriteLine("not connected");
                
                Form1 form = new Form1();
                form.SetText("XYZ");
                MakeNewConnection();
            }
        }
    }

    void MakeNewConnection()
    {
        webSocket.Connect();      
        Thread.Sleep(10000);
    } 
}
 

Форма:

 public void SetText(string text)
{
    if (InvokeRequired)
    {
        this.Invoke((MethodInvoker)delegate () { SetText(text); });
        return;
    }
    
    textBox1.Text  = text;
}
 

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

1. Это textBox1.Text =… соответствует действительности?

2. Проблема в том, что вы создаете экземпляр Form1 в фоновом потоке вашего BackgroundWorker (и не показываете форму).

3. @Steeeve Как я могу это исправить? если я использую private Form1 Form1; , я получаю, что форма 1 была нулевой

4. Вы объявляете Form1 как поле класса, но никогда не присваиваете этой переменной новый экземпляр. Вместо этого вы создаете новый экземпляр в рабочей процедуре BackgroundWorker и назначаете его локальной переменной. Чтобы исправить это, мы должны больше знать о вашей цели.

Ответ №1:

Websockets в winforms стало намного проще с помощью библиотеки от Мариуша Котаса, которая, возможно, неудивительно, называется Websocket.Клиент ; если вы откроете менеджер пакетов VS’ nuget и выполните поиск в нем, вы найдете его (в настоящее время около версии 4.3).

Настройка может выглядеть так:

 private WebsocketClient _cws;

private async void ConnectButton_Click(..){

    _cws = new WebsocketClient(new Uri("your uri here"));

    _cws.MessageReceived.Subscribe(msg => MessageReceived(msg.Text));

    _cws.DisconnectionHappened.Subscribe(info => DoSomething("Disconnection happened: "   info));
}
 

Отправка сообщения может выглядеть так:

 private async void ConnectButton_Click(..){
    _cws.Send(messageTextBox.Text);
}
 

Получение сообщения подписано выше:

 private void MessageReceived(string msg)

    //local function for logging
    void addAndScrollAsync()
    {
        _messagesListBox.Items.Add( msg);

        //this scrolls to show new messages while the listbox is at the bottom, but doesn't if it's been scrolled up
        int visibleItems = _messagesListBox.ClientSize.Height / _messagesListBox.ItemHeight;
        if (_messagesListBox.Items.Count > visibleItems amp;amp; _messagesListBox.TopIndex > _messagesListBox.Items.Count - visibleItems - 2)
            _messagesListBox.TopIndex = _messagesListBox.Items.Count - visibleItems   1;

    }

    _messagesListBox.InvokeEx(() => addAndScrollAsync());
        

}
 

У меня есть несколько вспомогательных расширений для любого вызова:

 public static class ControlExtensions
{
    public static TResult InvokeEx<TControl, TResult>(this TControl control,
                                               Func<TControl, TResult> func)
      where TControl : Control
    {
        return control.InvokeRequired
                ? (TResult)control.Invoke(func, control)
                : func(control);
    }

    public static void InvokeEx<TControl>(this TControl control,
                                          Action<TControl> func)
      where TControl : Control
    {
        control.InvokeEx(c => { func(c); return c; });
    }

    public static void InvokeEx<TControl>(this TControl control, Action action)
      where TControl : Control
    {
        control.InvokeEx(c => action());
    }
}
 

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

1. У вас есть какие-либо идеи, как я могу выполнить цикл с этим пакетом, который проверяет, подключен ли сокет к сети, или я могу получить статус с его помощью?

2. Я не думаю, что вам нужно беспокоиться об этом; после подключения он остается подключенным (и снова подключается, если происходит отключение), пока вы его не отключите. Я думаю, что на домашней странице проекта есть какая-то информация .. Посмотрите здесь и посмотрите, есть ли какой-нибудь более глубокий пример: github.com/Marfusios/websocket-client ?

3. (У него есть свойство isRunning, которое сообщит вам, подключен ли он.. Я никогда им не пользовался)

4. Хорошо, спасибо, этот пакет намного лучше

Ответ №2:

Вы не показываете свою форму. Добавьте form.Show() или form.ShowDialog() , в зависимости от того, хотите ли вы подождать, пока пользователь закроет форму.

Кроме того, я нашел этот метод расширения весьма полезным для внесения потокобезопасных изменений в элемент управления. Используйте его так: textBox1.InvokeSave(() => textBox1.Text = text); .

 public static partial class ControlExtensions
{
    public static void InvokeSave(this Control control, Action action)
    {
        Delegate del = action;

        try
        {
            if (control.InvokeRequired)
            {
                control.Invoke(del);
            }
            else action();
        }
        catch (ObjectDisposedException)
        {
            // guess do nothing is fine then
        }
    }
}
 

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

1. Теперь я вижу, что моя форма всегда перезагружается, но текстовое поле не меняется