views:

169

answers:

3

I have a process where an incoming user request to our system is being handled. I also want to add some metadata about the request to a database table without impacting the responsiveness of the main process. To achieve this I added a call to an asynchronous method like this:

public static ReturnObject ResponsiveMethod(string ip, string code)
{
   // ... some reasonably quick code

   IPDetail.InsertAsync(ip);  // <-- call to the async method

   return new ReturnObject(code);
}

The InsertAsync() method looks like this:

   public static void InsertAsync(string ipAddress)
   {
        Action action = () => IPDetail.Insert(ipAddress);
        action.BeginInvoke(aResult => Log.Debug("Completed Insert"), null);
   }

And finally, the normally non-asynchronous method called Insert():

    private static void Insert(string ipAddress)
    {
        ApplicationContextHelper.LoadApplicationContext();
        var helper = new GeoLocationHelper();
        var result = helper.GetDetailsFromIP(ipAddress);
        Log.InfoFormat("Succesfully retreived IP data {0}.", ipAddress);
        result.Save();
    }

In my unit tests the InsertAsync() call works perfectly. Inside the method calls in Insert() there are many operations occuring which are detailed by logging, and all the expected log messages are there, as well as the final result of the result.Save() method.

However, we have a webservice which utilizes something like the ResponsiveMethod() method above and for some reason the asynchronous calls do not complete. All of the logging in the LoadApplicationContext() method gets fired, but after that there is no log activity related to the Insert() and the result.Save() is never getting executed.

Revised summary question to be more concise

My current thinking is that the webservice has completed its task and the thread which called the asynchronous no longer exists. Would this stop the async call from completing?

A: 

My first thought is that you may be throwing an exception on your async call in the web service scenario for some reason. I know you've probably pared it down to post it on the web, but is there any "more-or-less unfailable" error handling code in there?

Clyde
There are a few exceptions possible, but they are pretty well handled and, at worst, would show a detailed log message before crapping out.
Sailing Judo
OK. You're async call should be on a ThreadPool thread so as far as I know it shouldn't matter if the original thread finishes and exits.
Clyde
+1  A: 

I've never used BeginInvoke before, but usually where there's a Begin*, you also need the coresponding End*. Please add one, along with correct exception handling.

John Saunders
I'm not exactly sure how I would place an EndInvoke in this scenario. I'm using Linq to perform the callback which generally works well (in my unit testing certainly). This is a case where I couldn't care less about a callback... I just want the new action to do its thing without blocking the calling process.
Sailing Judo
Since you don't understand what EndInvoke would have done, you can't know whether or not you need it. I suggest that you simultaneously have a problem you don't understand, and that there may be a connection between the two things that are not understood.
John Saunders
The MSDN docs do say: "No matter which technique you use, always call EndInvoke to complete your asynchronous call."http://msdn.microsoft.com/en-us/library/2e08f6yc.aspxNot sure if that's related to the problem you're seeing or not, though
Clyde
I'm starting to think you guys are right. The fact that the unit tests appear to work is a complete red herring. Just found this link talks more about what I was trying: http://tinyurl.com/7m7bje
Sailing Judo
A: 

Are you relying on the identity of the caller in the Async method call? The identity may be lost when called from the web service.

Gratzy
Good question, I wasn't sure because we do tend to use Identity quite a bit. However, I don't think this is the case here. The log trail stops well before any areas where the Identity might be used, and if it had been an issue an exception would have been raised and logged.
Sailing Judo