Search code examples
.netc#-4.0blockingautoresetevent

Getting rid of blocking code


I am not sure if I can explain it well here but let me give it a try. Code below is just to show the idea as I am just typing it here without verifying everything in the compiler.

I have a method (say Method1) where I am doing two things. 1. Calling a web-service method to perform an action. 2. After that, I am polling on same web-service object to wait until action results become available.

So basically something like as follows.

public class MyClass   
{   
  Method1()   
  {     
    // call Web service method  

    // code for polling    
  }  
}

However this approach makes Method1 blocking until action results become available as determined during polling. I want to change it such that caller of Method1 can return immediately after call to web service method and can somehow be signaled once web-service results are available. So I am thinking of having a AutoResetEvent object as class member that I set to signaled state during polling.

public class MyClass   
{   
  public AutoResetEvent autoEvent = new AutoResetEvent(false);
  Method1()   
  {     
    // call Web service method  

  }  

  Method2()   
  {     
    // code for polling    
    // change state of autoEvent to signaled once results are availble

  }  

}

With this approach, user of this API just call Method1 that returns immediately and they can just do wait on autoEvent to get signaled. The problem is that who is going to call Method2 in this case?


Solution

  • There's a couple of different methodologies for asynchronous code. The most common in .NET today is to utilize Tasks. For a basic example you can do something like:

    Task task = Task.Run(() => DoSomething());
    task.ContinueWith(() => DoAfterSomething());
    

    This allows the code to continue processing while the task is executed on a background thread. This might seem a bit wordy & clumbsy with all the lambdas and sub-methods, which is why the async\await pattern was introduced. This looks something like:

    Task<int> DoSomethingAsync()
    {
        // do something asynchronously..
    }
    
    async Task<int> ExampleAsync()
    {
       int result = await DoSomethingAsync();
       DoAfterSomething();
       return 42;
    }
    

    Note that DoAfterSomething may be called on a different thread than the original caller.

    Another methodology that is commonly used is the APM methodology. This involves two methods that kick off an async thread and another to complete it (usually BeginX and EndX). This commonly looks like:

    FileStream fStream = /* etc */
    byte[] buffer = /* etc */
    void ReadFile(FileStream fStream)
    {
        var asyncResult = fStream.BeginRead(buffer, 0 , buffer.Length, new AsyncCallback(EndReadCallback), null);
    }
    
    void EndReadCallback(IAsyncResult result)
    {
        int length = fStream.EndRead(result);
        // continue processing on buffer
    }
    

    Another methodology is the EAP model which uses events to trigger completion. This model isn't used much in the .NET framework, but it is in there. It is used something like:

    WebDownload download = /* etc */
    download.DownloadComplete += (buffer) => { /* do something with buffer */ };
    download.Get("http://foo/img.jpg");
    

    Personally, I use async\await for everything I create, but the other methodologies are good to know in case you encounter them in legacy components. If you ever need to convert APM or EAP to task based, you can do this pretty easily with Task.Factory.FromAsync or using TaskCompletionSource