views:

106

answers:

4

Here is what I do in a controller action:

  1. create and start a new Thread that does a relatively long processing task (~30 seconds on average, but might be several minutes)
  2. immediately return the page response so the user knows processing has started (trivially, a Json with a task ID for polling purposes).

At some random point, ThreadAbortException is thrown, so the async task does not complete. The exception is not thrown every time, it just happens randomly roughly 25% of the times.

Points to note:

  • I'm not calling Response.End or Response.Redirect - there isn't even a request running when the exception is thrown
  • I tried using ThreadPool and I got the same behavior
  • I know running threads in ASP.NET has several caveats but I don't care right now

Any suggestion?

+2  A: 

The problem is you shouldn't do it this way. If you need a task to run for a long period of time in the background ASP.Net should either spawn a process to handle it or add the work item to a queue for a Windows Service to handle.

Spencer Ruport
Sorry Spencer, but I've said already that I know it's a sub-optimal way of doing async processing, but there isn't another way in my case.
Dario Solera
Unfortunately it's not simply sub-optimal. It's actually wrong and not designed for such use. Tracking down ways to determine how to keep IIS from terminating your long running thread will likely be a hack job with unforeseen consequences. If there isn't another way then there is something wrong with your environment.
Spencer Ruport
I agree with you. At any rate, I figured a way to spawn a process, I just have to verify it works.
Dario Solera
A: 

Does this help since you want to fire and forget.

"Delegates provide a method called BeginInvoke that allows us to call the delegate asychronously."

http://hackingon.net/post/Asynchronous-fire-and-forget-method-calls-in-NET.aspx

Raj Kaimal
I will give it a try, however I suspect that the behavior will be the same. Moreover, the need to call EndInvoke complicates things as the original thread that started the invocation is a ASP.NET ThreadPool thread, so it might be already in use to serve another request.
Dario Solera
A: 

How about using an Asynchronous controller?

SeanX
That would be the obvious choice, but I can't seem to figure how to report progress to the user in a simple way. In the end, the user sees the page "stuck" for a long time, and that is not acceptable. I would have to use AJAX calls anyway, so I think I'll first try the process solution suggested by Spencer.
Dario Solera
A: 

The problem was that the app was being recycled. I perfectly know that when that happens, all threads are aborted, I didn't expect the application to recycle. The reason is that the async process used changed temp files stored in the app root, and that caused a recycle.

I feel dumb.

Dario Solera