超时结束后,事件被触发
-
25-10-2019 - |
题
我必须等待触发事件。我最初的解决方案是使用 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
有人知道是什么原因导致了这个问题,以及如何解决问题?
编辑:不再相关。转发了OnRreresponserrived事件,因为我没有及时找到其他解决方案。
解决方案
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应用程序,那么您应该考虑执行 全部的 背景线程中的内容,然后在完成后通知UI。当然,如果您需要帮助,您将需要提供更多详细信息。