views:

121

answers:

3

Problem: I am working on a ASP.NET 2.0/C# Application and I need to do the following:

I have a function I am using from a third-party library lets say

MyFunctions.CalculateTotal(int a, int b);

A known issue is that the thread locks resources. So there is another function that needs to be called afterwards to clean everything up.

MyFunctions.ThreadExit();

The issue is that this will exit the current thread and I will not be able to use any other function afterwards. Also, it does not seem appropriate for me to kill an asp.net thread like this.

I have considered spinning a separate thread, but that would be a hack.

Global.asax has those application wide events like Application_Start/End

I know there is no event such as Application_ThreadStart/End, but maybe something like that?

Any other suggestion for a possible solution?

+2  A: 

I'm not sure that using a separate thread would be such a hack. It sounds like that is what required.

BTW - that third party library sounds absolutely horrible! ;-)

AdamRalph
+3  A: 

(Updated)

It sounds like that library wants to make a mess in the current thread and force you to exit the thread if you want it to clean up after itself. In that case, I would always run that method in a separate thread. Untested code:

int result;
var thread = new Thread(_ => {
  result = MyFunctions.CalculateTotal(a, b);
  MyFunctions.ThreadExit();
}).Start();
gWiz
sorry I corrected my post to say instead. A known issue is that the thread locks resources. So there is another function that needs to be called afterwards to clean everything up.
hmak
Ah okay. I think I would still go with this approach. You basically make the call into that 3rd party library on its own thread. That way you it has it's own execution/thread context that it can clean up at the end.
gWiz
do you know of anything in asp.net that I could take advantage of so I don't have to setup this up each time?
hmak
You can create a wrapper class for the library. The most straightforward approach would be a static class that simply exposes each of the methods in MyFunctions in a proxy method that implements the pattern above. However, bear in mind that Thread management is expensive, and this might not be ideal in your particular usage scenario. If you're calling into it 50x per second, you might consider the (much more advanced) producer/consumer pattern to manage the threads. OTOH, if your load is "bursty" and inconsistent, the above pattern, or the ThreadPool, might be worth consideration.
gWiz
thanks, I will consider those options.
hmak
@wingho: I think this may be the only library so badly broken that it needs a separate cleanup method. It would be surprising if ASP.NET had a fix for that.
John Saunders
A: 

This article might help you, it involves using an IHttpAsyncHandler - you would then use this as "asynchandler.ashx". It does require you to know a bit about HttpHandlers if you don't already though, so it's not an instant solution.

A slightly modified version of their code with your MyFunctions is:

public class AsyncHandler : IHttpAsyncHandler
{ 
  public void ProcessRequest(HttpContext ctx)
  {
    // not used
  }

  public bool IsReusable
  {
    get { return false;}
  }

  public IAsyncResult BeginProcessRequest(HttpContext ctx, 
                                          AsyncCallback cb, 
                                          object obj)
  {
    AsyncRequestState reqState = 
                      new AsyncRequestState(ctx, cb, obj);
    AsyncRequest ar = new AsyncRequest(reqState);
    ThreadStart ts = new ThreadStart(ar.ProcessRequest);
    Thread t = new Thread(ts);
    t.Start();

    return reqState;
  }

  public void EndProcessRequest(IAsyncResult ar)
  {
    AsyncRequestState ars = ar as AsyncRequestState;
    if (ars != null)
    {
     // here you could perform some cleanup, write something else to the
     // Response, or whatever else you need to do
    }
  }
}

public class AsyncRequest
{
  private AsyncRequestState _asyncRequestState;

  public AsyncRequest(AsyncRequestState ars)
  {
    _asyncRequestState = ars;
  }

  public void ProcessRequest()
  {
    MyFunctions.CalculateTotal(int a, int b);

    // tell asp.net I am finished processing this request
    _asyncRequestState.CompleteRequest();
  }
}

Change their variable names are they're nasty.

Chris S