Winforms - Вопрос о регистрации / отмене регистрации событий - PullRequest
1 голос
/ 12 августа 2011

Я занимаюсь разработкой приложения C # WinForms.Это приложение MDI, которое содержит две формы внутри него.В любое время будет включена только одна из форм.Приложение имеет две темы.Один поток является основным потоком (поток, который управляет GUI).У меня также есть другой поток, работающий в фоновом режиме, который прослушивает TCP-сообщения от сервера (это поток "Client").Когда я получаю одно из этих сообщений, поток клиента запускает событие в поток GUI.Так, например, вот упрощенный пример того, как у меня все изложено в коде:

Список возможных событий в потоке клиента:

    public event EventHandler<ConnectEventArgs> ConnectEvent = delegate { };
    public event EventHandler<DisconnectEventArgs> DisconnectEvent = delegate { };
    public event EventHandler<EdgeMessageEventArgs> EdgeMessageEvent = delegate { };
    public event EventHandler<ServerModeEventArgs> ServerModeEvent = delegate { };
    public event EventHandler<SpreadDataEventArgs> SpreadDataEvent = delegate { };

Форма # 1, регистрирующаяся для событий:

        m_Client.ConnectEvent               += new EventHandler<ConnectEventArgs>(OnConnectEvent);
        m_Client.DisconnectEvent            += new EventHandler<DisconnectEventArgs>(OnDisconnect);
        m_Client.EdgeMessageEvent           += new EventHandler<EdgeMessageEventArgs>(OnEdgeMessageEvent);

Форма № 2, регистрируемая для событий:

        m_Client.ConnectEvent += new EventHandler<ConnectEventArgs>(OnConnectEvent);
        m_Client.DisconnectEvent += new EventHandler<DisconnectEventArgs>(OnDisconnect);
        m_Client.SpreadDataEvent += new EventHandler<SpreadDataEventArgs>(OnSpreadDataEvent);

Основная форма (окно MDI) регистрируется для одного события:

        m_Client.ServerModeEvent    += new EventHandler<ServerModeEventArgs>(OnServerModeEvent);

Когда приложение запускаетсявверх, пользователь подключается к серверу.Как только клиент подключается к серверу, запускается ConnectEvent.Сразу после этого запускается ServerModeEvent.Это в основном определит, какая форма будет использоваться в приложении.Проблема, с которой я сталкиваюсь, заключается в том, как выполнить всю регистрацию / отмену регистрации событий в этих формах потокобезопасным способом.

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

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

Я слышал о "слабых событиях" и думал, что это может быть ответом на мою проблему.,Я действительно не знаю, как реализовать это в моем приложении, хотя.Есть какие-нибудь мысли по поводу проблемы, с которой я столкнулся?Могу ли я использовать слабые события?Что-то еще?

1 Ответ

0 голосов
/ 13 августа 2011

Если вы используете Control.Invoke для отправки событий из вашего клиентского потока в ваш поток пользовательского интерфейса, клиентский поток будет заблокирован, пока поток пользовательского интерфейса не завершит обработку события;Это означает, что у вас не будет возможности вызвать асинхронное событие, пока вы настраиваете обработчики событий в потоке пользовательского интерфейса.(Это предполагает, что ваш клиентский поток на самом деле является отдельным потоком, который не является асинхронным внутри себя.)

Если вы используете Control.BeginInvoke , однако, клиентский поток не блокируется, покапоток пользовательского интерфейса обрабатывает событие.Преимущество заключается в том, что клиентскому потоку никогда не приходится ждать пользовательского интерфейса, но компромисс заключается в том, что вам, вероятно, потребуется заранее зарегистрировать все свои события на клиентском объекте, поскольку он может развернуться и отключить событие до того, какПоток пользовательского интерфейса имел возможность настроить обработчики событий для него.Фактически, клиентский поток может отправить несколько событий, прежде чем поток пользовательского интерфейса даже получит возможность начать обрабатывать первый (в этом случае они помещаются в очередь и обрабатываются по порядку потоком пользовательского интерфейса).

Решение, таким образом, заключается в том, чтобы использовать Invoke, когда вам требуется синхронная обработка события клиентом;и BeginInvoke, когда вы этого не сделаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...