8

I have a function that needs to be executed only when a callback is received from asynchronous function.

Like

I call asynchronous function Stop() and soon after that I call asynchronous function Start().

The Issue before Stop CallBack is received Start() is called and thus I am getting issues. Also I can not separate the calling of two functions Like I can not do this.:

public void SomeFunction()
{
    Stop();
}  

public void Stop_CallBack(eventargs e)
{
    Start();
}

I have to do this:

public void SomeFunction()
{

  Stop();
  //Do something;

  Start();
}

but before I receive Stop call back my start() function is executed thus creating the problems for me.

Can anyone help me out how can I solve this issue.

kapa
  • 77,694
  • 21
  • 158
  • 175
Sumit
  • 2,932
  • 6
  • 32
  • 54

2 Answers2

25

This is when you want to use wait handles. Here is a short code sample to show one approach:

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();
    }

}
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • 1
    Can you explain why you need `Stop_Callback`? Why not call `stopWaitHandle.Set();` directly in the task? – Daniel Hilgarth Jun 10 '11 at 12:20
  • 3
    @Daniel: *I* don't need it; but the question states *"[...] function that needs to be executed only when a callback is received [...]"* and the OP had already suggested such a callback in the given code sample. I tend to like to restructure OP code as little as possible. It could be that the callback is invoked from 3rd party code that does not have access to the wait handle for instance. – Fredrik Mörk Jun 10 '11 at 12:23
  • I can not call Stop_callback. This is the call back I receive from some other application. – Sumit Jun 10 '11 at 12:26
  • 2
    @Sumit: The `Task` in my sample is only for having a fully working sample. If I understand this correctly, you pass `Stop_Callback` as an argument when invoking an asynchronous library method, which will call that method when finished? If so, my sample is still valid, only that you will call that async method instead of having a task. – Fredrik Mörk Jun 10 '11 at 12:28
4

Since these look like member functions, you can add an event member variable (either a ManualResetEvent or an AutoResetEvent. Then in the Stop() method you set the event to signaled. In between the calls to Stop() and Start() you wait for the event.

private AutoResetEvent _stopped = new AutoResetEvent(false);

public void SomeFunction()
{
     Stop();
     _stopped.WaitOne();
     Start();
}

In the stop function you would do

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

If using a 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
}
pstrjds
  • 16,840
  • 6
  • 52
  • 61
  • I have already tried with AutoResetEvent and ManualRestEvent and it didnt worked – Sumit Jun 10 '11 at 12:28
  • If you use a ManualResetEvent then you have to reset it (`_stopped.Reset()`) after the WaitOne call, otherwise it stays in a signaled state. – pstrjds Jun 10 '11 at 12:32
  • What do you mean by it didn't work with the Auto and Manual reset events? Your code didn't block at the WaitOne() call? In that case could you post more of the code? If you have a function that is calling Stop, doing something and then calling Start. As long as the event is being signaled in the Stop and only reset in the start then your code will block at the WaitOne until the event is signaled. – pstrjds Jun 10 '11 at 19:28
  • I mean my code got blocked at WaitOne() but it blocked everything, I was not able to receive call back for Stop(), my code was blocked for infinite time. can you tel me what could be the reason ? – Sumit Jun 11 '11 at 07:52
  • You should move the setting of the wait handle into the callback function. I was not sure on the ordering of your code. (see @Fredrik's answer). The WaitOne() will block until the handle is signaled (`Set()` is called). – pstrjds Jun 13 '11 at 12:51