Вопрос

Я должен ждать, пока событие будет вызвано. Моим первоначальным решением было использовать AutoResetEvent а также WaitOne(), но событие было всегда Спущено сразу после того, как время ожидания закончилась. Поэтому я вернулся к подходу ниже, но у меня все еще есть такая же проблема. Через 2 или 3 секунды после того, как тайм -аут заканчивается событием, независимо от того, каким был тайм -аут.

_wait = true;
_delayedResponse = null;

var thread = new Thread(delegate
{
        while (_wait)
        {
           Thread.Sleep(500);
           if (_delayedResponse != null)
               return;
        }
});

thread.Start();
var received = thread.Join(_responseTimeout);
_wait = false;

if (!received)
    throw new TimeoutException(
        "Timeout for waiting for response reached.");

return _delayedResponse;

Вот код обработчика событий:

private void OnResponseArrived(object sender, ResponseEventArgs args)
{
    _delayedResponse = args.VerificationResponse;
}

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

var result = DoStuff(); // Library function that is responsible for the event 
if (result.Status == Status.Wait)
   Wait(); // Function above

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

РЕДАКТИРОВАТЬ: больше не актуально. Перестал событие в отношении ресурсов, потому что я не нашел другого решения во времени.

Это было полезно?

Решение

Thread.Join является блокирующим вызовом - он остановит поток, которую вы звоните, выполнять любую другую работу. Я предполагаю, что ты ожидающий Для события в фоновом потоке, но код, который поднимет ваше мероприятие, работает в том же потоке, что и опубликованный вами код.

Позвонив thread.Join Вы блокируете нить, которая должна выполнять вашу обработку. Итак, вы ждете, пока истекает время ожидания ... тогда какой бы метод был завершен ... тогда Ваша обработка на самом деле происходит, и ResponseArrived событие поднято.

Было бы полезно, если вы опубликуете остальную часть своего кода, но суть решения будет заключаться в выполнении фактической работы (какой бы код поднимает ResponseArrived Событие) В фоновом потоке - и удалите дополнительное поток из опубликованного вами кода.

РЕДАКТИРОВАТЬ В ответ на комментарий ...

Чтобы синхронизировать ваши две части кода, вы можете использовать AutoResetEvent. Анкет Вместо использования Thread.Sleep И ваш другой код, попробуйте что -то вроде этого:

// create an un-signalled AutoResetEvent
AutoResetEvent _waitForResponse = new AutoResetEvent(false);

void YourNewWorkerMethod()
{
    _delayedResponse = null;
    var result = DoStuff();

    // this causes the current thread to wait for the AutoResetEvent to be signalled
    // ... the parameter is a timeout value in milliseconds
    if (!_waitForResponse.WaitOne(5000))
        throw new TimeOutException();

    return _delayedResponse;
}


private void OnResponseArrived(object sender, ResponseEventArgs args)
{
    _delayedResponse = args.VerificationResponse;
    _waitForResponse.Set();  // this signals the waiting thread to continue...
}

Обратите внимание, что вам нужно избавиться от AutoResetEvent Когда ты закончишь с этим.

Другие советы

Ну, первое, что вам нужно сделать, это убедиться, что DoStuff На самом деле работает в фоновой ветке.

Если это правильно, то, как пишется ваш код прямо сейчас, вам не нужно появиться в втором потоке, просто чтобы присоединиться к нему в одну строку ниже, что -то подобное будет просто работать (в качестве теста):

// handler needs to be attached before starting
library.ResponseReceived += OnResponseReceived;

// call the method
var result = library.DoStuff();

// poll and sleep, but 10 times max (5s)
int watchdog = 10;
while (_delayedResponse == null && watchdog-- > 0)
   Thread.Sleep(500);

// detach handler - always clean up after yourself
library.ResponseReceived -= OnResponseReceived;

Console.WriteLine(_delayedResponse != null);

Если это работает, и вы программируете приложение Winforms, то вам следует рассмотреть возможность сделать весь вещь в фоновой ветке, а затем уведомление пользовательского интерфейса, когда он закончен. Конечно, вам нужно будет предоставить более подробную информацию, если вам нужна помощь с этим.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top