如何在收到异步函数的回调之前使线程休眠?

Posted

技术标签:

【中文标题】如何在收到异步函数的回调之前使线程休眠?【英文标题】:How to Sleep a thread until callback for asynchronous function is received? 【发布时间】:2011-09-12 11:11:05 【问题描述】:

我有一个函数,只有在从异步函数接收到回调时才需要执行。

喜欢

我调用异步函数Stop(),不久之后我调用异步函数Start()

收到停止回调之前的问题Start() 被调用,因此我遇到了问题。我也不能分开调用两个函数就像我不能这样做。:

public void SomeFunction()

    Stop();
  

public void Stop_CallBack(eventargs e)

    Start();

我必须这样做:

public void SomeFunction()


  Stop();
  //Do something;

  Start();

但在我收到 Stop 回调之前,我的 start() 函数被执行,从而给我带来了问题。

谁能帮我解决这个问题。

【问题讨论】:

【参考方案1】:

这是您想要使用等待句柄的时候。下面是一个简短的代码示例来展示一种方法:

class AsyncDemo

    AutoResetEvent stopWaitHandle = new AutoResetEvent(false);
    public void SomeFunction()
        
        Stop();
        stopWaitHandle.WaitOne(); // wait for callback    
        Start();
    
    private void Start()
    
        // do something
    
    private void Stop()
    
        // This task simulates an asynchronous call that will invoke
        // Stop_Callback upon completion. In real code you will probably
        // have something like this instead:
        //
        //     someObject.DoSomethingAsync("input", Stop_Callback);
        //
        new Task(() =>
            
                Thread.Sleep(500);
                Stop_Callback(); // invoke the callback
            ).Start();
    

    private void Stop_Callback()
    
        // signal the wait handle
        stopWaitHandle.Set();
    


【讨论】:

你能解释一下为什么需要Stop_Callback吗?为什么不在任务中直接调用stopWaitHandle.Set();呢? @Daniel:不需要它;但问题指出 "[...] 仅在收到回调时才需要执行的函数 [...]" 并且 OP 已经在给定的代码示例中建议了这样的回调。我倾向于尽可能少地重构 OP 代码。例如,回调可能是从无权访问等待句柄的第 3 方代码调用的。 我无法调用 Stop_callback。这是我从其他应用程序收到的回调。 @Sumit:我的示例中的Task 仅用于拥有一个完全工作的示例。如果我理解正确,您在调用异步库方法时将Stop_Callback 作为参数传递,完成后将调用该方法?如果是这样,我的示例仍然有效,只是您将调用该异步方法而不是执行任务。【参考方案2】:

由于这些看起来像成员函数,您可以添加一个事件成员变量(ManualResetEventAutoResetEvent。然后在 Stop() 方法中将事件设置为已发出信号。在调用 Stop( ) 和 Start() 你等待事件。

private AutoResetEvent _stopped = new AutoResetEvent(false);

public void SomeFunction()

     Stop();
     _stopped.WaitOne();
     Start();

在你会做的停止功能中

private void Stop()

    try
    
         // Your code that does something to stop
    
    finally
    
         _stopped.Set();  // This signals the event
    

如果使用ManualResetEvent -

private ManualResetEvent _stopped = new ManualResetEvent(false);

public void SomeFunction()

     Stop();
     _stopped.WaitOne();
     Start();


private void Stop()

    try
    
         // Your code that does something to stop
    
    finally
    
         _stopped.Set();  // This signals the event
    


private void Start()

    _stopped.Reset();

    // Your other start code here

【讨论】:

我已经尝试过 AutoResetEvent 和 ManualRestEvent,但没有成功 如果您使用 ManualResetEvent,那么您必须在 WaitOne 调用后重置它 (_stopped.Reset()),否则它会保持在信号状态。 你的意思是它对自动和手动重置事件不起作用?您的代码没有在 WaitOne() 调用中阻塞?在那种情况下,您可以发布更多代码吗?如果你有一个调用 Stop 的函数,做某事然后调用 Start。只要事件在 Stop 中发出信号并且仅在开始时重置,那么您的代码将在 WaitOne 处阻塞,直到发出事件信号为止。 我的意思是我的代码在 WaitOne() 处被阻止,但它阻止了一切,我无法收到 Stop() 的回调,我的代码被无限期地阻止。你能告诉我可能是什么原因吗? 您应该将等待句柄的设置移动到回调函数中。我不确定您的代码的顺序。 (见@Fredrik 的回答)。 WaitOne() 将阻塞直到句柄发出信号(Set() 被调用)。

以上是关于如何在收到异步函数的回调之前使线程休眠?的主要内容,如果未能解决你的问题,请参考以下文章

如何使单独的同步功能等待另一个异步功能?

nodejs中的异步回调机制

GWT 单线程异步回调

JavascriptJs同步异步以及回调函数

js回调函数如何实现异步,给一个例子

只有在回调/异步函数内部时,Axios 请求才会收到 CORS 错误