Member 13164579 Ответов: 1

Обновление текста в моем основном графическом интерфейсе из асинхронного потока


Привет.

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

Теперь я использую обратный вызов Asyn на серверном классе, который срабатывает при обнаружении данных, и я хотел бы, чтобы мой основной графический интерфейс обновил текст состояния, чтобы сказать "данные получены", но я не имею понятия, как отправить текст обратно в основной графический интерфейс.

Какие-нибудь указания, пожалуйста? Я погуглил и обнаружил, что делегаты могут быть ответом, но это кажется таким сложным?

Спасибо

Что я уже пробовал:

Какие-нибудь указания, пожалуйста? Я погуглил и обнаружил, что делегаты могут быть ответом, но это кажется таким сложным?

Спасибо

1 Ответов

Рейтинг:
9

Afzaal Ahmad Zeeshan

Концепция фоновых потоков в .NET framework настолько запутана, что иногда не имеет никакого отношения к тому, что вы на самом деле делаете.

Если бы мне пришлось написать такое приложение в сегодняшней версии, я бы выбрал асинхронное / ожидающее программирование, а не Делегатский способ, потому что,

1. делегатов трудно понять и правильно запрограммировать.
2. у делегатов есть и другие вещи, которые нужно обрабатывать; обратные вызовы и т. д.
3. .NET имеет async/await, которые предназначены для замены асинхронного программирования делегатами и функциями begin/end.

Однако концепция async/await в этом случае будет проще. Из-за того, что вы оставите большую часть асинхронного программирования самому фреймворку. Кроме того, .NET framework имеет несколько Async функции, которые возвращают Task объекты. Мы можем использовать их и программировать наши приложения асинхронно. Что-то вроде этого,

public MainForm() {

    // Call to start the server here.
    startServer();
}

private void startServer() {
    server = new TcpListener(); // Pass your values

    // You need to rewrite this, it is just off the top of my head
    // Maybe taking this inside the listen function, and running a 
    // while(true) loop would be a better approach; but try either and chose.
    while(true) { 
        listen();
    }
}

private async void listen() { 
    // This will asynchronously listen
    var client = await server.AcceptTcpClientAsync(); 

    // Client was captured
    label.Text = "Client Connected";
    // Continue
}

Причина, по которой я предлагаю async/await вместо делегатов, заключается в простоте и других функциях; меньше ресурсов потребляется в async/await, потому что есть только одна нить делать все, если вы не укажете использовать больше.

Ах да, вы также можете изменить это для работы с классом сокетов, я чувствую, что конкретный класс TCP будет более простым и удобным. :-)

Класса Tcplistener (Системы.Нет.Розетки)[^]

Еще одна вещь, вам не нужно обрабатывать диспетчер или вызов здесь, потому что в коде async/await только один поток обращается к ресурсам, таким образом, нет необходимости загружать код обновления пользовательского интерфейса обратно в насос диспетчера.

Обновление

Я могу придумать несколько способов отправки и обновления текста в основной форме, два из них:,

1) Создайте статическое поле метки в форме и установите его на метку, которую вы хотите обновить, а затем используйте это поле из класса сервера.
public class MainForm {
    public static Label MyLabel { get; set; }

    public MainForm() {
        // Other constructor code
        MyLabel = this.label1;
    }
}

// Somewhere in the server code, 
public void listen() {
    // your server code, 
    MainForm.MyLabel.Text = "Updated text";
}

// Or you can have a separate function that updates the field, 
public void updateLabel (string message) {
    MainForm.MyLabel.Text = message;
}


2) Другой способ-передать ссылку на вашу текущую основную форму классу сервера, чтобы сервер мог использовать этот объект и обновлять его значения. Это несколько двусмысленный подход, поэтому я не буду рекомендовать, но просто так, чтобы вы знали,

public class Server {
    public static MainFrom parentForm { get; set; } // Can be instance as well
    public Server(MainForm referenceForm) {
       parentForm = referenceForm;
    }

    // Then update
    public void updateField(string message) {
        parentForm.label1.Text = message;
    }
}


И конечно, у вас могут быть и другие способы. Все они работают довольно похоже,вам нужно передать ссылку, а затем через эту ссылку.


Member 13164579

Привет Afzaal. Спасибо Вам за это решение, но я думаю, что не объяснил себя правильно. На самом деле, я использую вышесказанное для своего сервера, но это не совсем то, что я пытаюсь выяснить, я очень устал, когда писал свой вопрос, поэтому постараюсь объяснить лучше.

У меня есть приложение основной формы, и на нем у меня есть кнопка для запуска моего сервера. У меня есть сервер класса CServer. cs.

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

Теперь в моей основной форме у меня есть строка состояния, и я хотел бы обновить текст из моего серверного класса/объекта, но это то, с чем я борюсь.

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

Я действительно пытался погуглить, но на самом деле не знаю, что я ищу, поэтому мне трудно найти решение.

Спасибо еще раз

Afzaal Ahmad Zeeshan

О, ладно.

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

Пожалуйста, смотрите обновление в ответе выше.

Member 13164579

Идеальный. Спасибо Afzaal, высоко ценится.

С уважением