超时结束后触发事件
我必须等待事件被触发。我最初的解决方案是使用 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
有谁知道导致这个问题的原因以及我如何解决它?
编辑:不再相关。转发了OnResponseArrived事件,因为我没有及时找到其他解决方案。
I have to wait for an event to be triggered. My initial solution was to use AutoResetEvent
and WaitOne()
, but the event was always triggered just after the waiting timeout was over. So I went back to the approach below, but I still have the same problem. 2 or 3 seconds after the timeout is over the event gets triggered no matter what the timeout was.
_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;
Here is the event handler code:
private void OnResponseArrived(object sender, ResponseEventArgs args)
{
_delayedResponse = args.VerificationResponse;
}
The event itself is triggered from another functions that calls the function above.
Basically it looks like this:
var result = DoStuff(); // Library function that is responsible for the event
if (result.Status == Status.Wait)
Wait(); // Function above
Does anyone have an idea what causes this problem and how I can solve it?
EDIT: No longer relevant. Forwarded the OnResponseArrived event, because I found no other solution in time.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
Thread.Join
是一个阻塞调用 - 它会阻止您正在调用的线程执行任何其他工作。我的猜测是,您正在后台线程上等待事件,但是引发事件的代码与您发布的代码运行在同一线程上。通过调用
thread.Join
你正在阻塞应该进行处理的线程。因此,您等待超时到期...然后无论您发布的代码采用哪种方法都会完成...然后您的处理实际上发生并引发ResponseArrived
事件。如果您发布其余的代码,这将很有用,但解决方案的要点是在后台线程中运行实际工作(无论代码引发 ResponseArrived 事件) - 并删除您发布的代码中的额外线程。
编辑以回应评论...
为了同步您的两段代码,您可以使用
AutoResetEvent
。不要使用 Thread.Sleep 和其他代码,而是尝试如下操作:请注意,在使用完 AutoResetEvent 后,您需要将其释放。
Thread.Join
is a blocking call - it'll stop the thread you're calling from doing any other work. My guess is that you're waiting for the event on a background thread, but the code that will raise your event is running on the same thread as the code you posted runs in.By calling
thread.Join
you're blocking the thread that should be doing your processing. So, you wait for your timeout to expire... then whichever method your posted code is in completes... then your processing actually happens and theResponseArrived
event is raised.It would be useful if you'd post the rest of your code, but the gist of the solution will be to run the actual work (whatever code raises the
ResponseArrived
event) in a background thread - and remove the extra threading from the code you posted.EDIT in response to comment...
In order to synchronise your two pieces of code, you can use an
AutoResetEvent
. Instead of usingThread.Sleep
and your other code, try something like this:Note that you'll need to dispose of the
AutoResetEvent
when you're done with it.好吧,您需要做的第一件事是确保 DoStuff 实际上在后台线程中工作。
如果这是正确的,按照您现在编写代码的方式,您不需要生成第二个线程,只需将其加入到下面一行,类似这样的事情就可以工作(作为测试):
如果这有效,如果您正在编写 WinForms 应用程序,那么您应该考虑在后台线程中完成整个工作,然后在完成时通知 UI。当然,如果您需要帮助,您需要提供更多详细信息。
Well, the first thing you need to do is make sure that
DoStuff
actually works in a background thread.If that is correct, the way your code is written right now, you don't event need to spawn a second thread, just to join it one line below, something like this would simply work (as a test):
If this works, and you are programming a WinForms app, then you should consider doing the entire thing in a background thread, and then notifying the UI when it's finished. Of course, you will need to provide more details if you need help with that.