Как я могу получить обработчик события для вызова из отдельного потока, чем тот, на котором он был создан? - PullRequest
1 голос
/ 19 апреля 2009

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

Это все работало нормально, пока я не добавил другую форму, которая появляется перед формой индексации. Теперь форма индексации открывается в другом потоке (через Application.Run () и второй поток). Проблема в том, что обработчик событий больше не вызывается при запуске события.

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

Ответы [ 2 ]

3 голосов
/ 19 апреля 2009

Элементом управления пользовательского интерфейса нужно манипулировать в потоке, в котором он был создан (поток в пользовательском интерфейсе). Чтобы достичь этого, вам нужно «вызвать» обработчик события.

Это можно сделать, подняв событие так:

EventHandler handler = myEventHandler;
if( handler != null )
{
    ISynchronizeInvoke target = handler.Target as ISynchronizeInvoke;

    if( target != null && target.InvokeRequired )
    {
        target.Invoke (handler, ... );
    }
    else
    {
        handler.DynamicInvoke (...);
    }
}

Или вы также можете взглянуть на AsyncOperation & AsyncOperationManager классы.

Или, может быть, даже проще, взгляните на класс SynchronizationContext . Используя свойство 'Current' этого класса, вы можете просто опубликовать делегат SendOrPostCallback, который оборачивает ваш обработчик событий.

0 голосов
/ 19 апреля 2009

Я не думаю, что это «механизм безопасности». Механизм безопасности, который действительно существует в WinForms (начиная с .NET 2.0 и далее), вызывает исключение, если вы находитесь в отладчике и пытаетесь получить доступ к пользовательскому интерфейсу из потока, отличного от соответствующего.

Вы уверены, что событие вообще не вызывается ? Это звучит очень странно. Если вы поставили точку останова на обработчик событий в отладчике, не будет ли эта точка останова поражена?

Чтобы ответить на ваш вопрос иначе, я бы не заставлял весь обработчик событий выполняться в определенном потоке. Может быть подписано более одного обработчика, и эти обработчики могут потребоваться для выполнения в разных потоках. Вместо этого я бы сделал обработчики событий сами по себе потокобезопасными - закодируйте их так, чтобы, если им нужно было выполнить какое-то действие в определенном потоке, они выполняли маршалинг обратно в поток (например, с помощью Control.BeginInvoke и т. Д.).

В каком потоке происходит большая часть вашего доступа к сети? Я надеюсь, что это не или вовлеченных потоков пользовательского интерфейса (в противном случае вы можете получить неотвечающий пользовательский интерфейс). Это означало бы, что, если бы это работало раньше, вы, вероятно, уже выполняете соответствующую сортировку ... очень странно.

Если ничего из этого не помогло, не могли бы вы придумать короткую, но полную программу, которая демонстрирует проблему? Проще диагностировать конкретный код:)

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