views:

889

answers:

3

Hi,
I got started with threads Thread.Start() recently and Long Running Tasks and noticed several request related issues.

EDIT

What would you suggest to provide the user a feedback while the job is being processed, make efficient use of the thread pool and make use of HttpContext if possible?

A: 

HttpContext.Current property of HttpContext object is static. And it can be used when in different threads or in the assemblies in the App_Code. But, it returns HttpContext object of the current Request.

All static properties of HttpContext are thread safe. And all the instance properties of HttpContext are not thread safe.

Pradeepneo
The result of HttpContext.Current depends on what thread your in, so your advice is not correct.
Frank Schwieterman
Please note that I have mentioned, "But, it returns HttpContext object of the current Request." So, if you are not in the context of request (out of boundary) HttpContext.Current will obviously return null no matter what thread you are in.
Pradeepneo
+2  A: 

You are quite possibly making a mistake in your use of threads in an ASP.NET application. Are you using asynchronous pages, or are you using new Thread().Start? The latter is a mistake, and can get you into some of those problems with HttpContext, when the request is complete, but the thread is still running.

Please edit your question to give more detail on what you're doing with threads.

John Saunders
question edited
Maxime
Thank you. You _are_ making a mistake. Long-running tasks should not be performed as part of the web application. They should be sent to another service for execution. The ASP.NET infrastructure is not made to deal with long-running tasks.
John Saunders
What do you suggest to provide the user a feedback while the job is being processed, make efficient use of the thread pool and make use of HttpContext if possible?
Maxime
You can't provide feedback _to_ the user. The user is the browser. The browser can use AJAX to query the status of the operation. You cannot use `HttpContext` for this.
John Saunders
OK let's just say, a "Please Wait..." while the job is being processed. Asynch. pages will block rendering no!?
Maxime
No! Where do you _get_ these ideas? And a "Please wait" is just making a div visible. It could even contain one of those cool animated gif's to fool the user into thinking something is happening.
John Saunders
http://msdn.microsoft.com/en-us/magazine/cc163725.aspx
Maxime
That's the canonical article on async pages. Where do you see it saying that this blocks rendering? The word "blocks" doesn't even appear in the article.
John Saunders
"Between the time Begin returns and End gets called, the request-processing thread is free to service other requests, and until End is called, rendering is delayed"<br />But I believe you if you say that I won't have a white loading page while the long running task is being processed. ;p
Maxime
No, I thought I'd gotten you away from "long-running task in ASP.NET". The task does not belong in ASP.NET. Move it out to a separate service. Have the page query for completion status or progress, and update an AJAX UI on that basis. Async pages are not for "long" running tasks. They're for tasks that will take 2 seconds. The idea is to not tie up worker threads for 2 seconds, when they'll just be blocked for 1.8 seconds.
John Saunders
Sorry for giving you so much troubles. So a Web Service processing the task and somehow a Status Class plus an AJAX UI?
Maxime
If it was trouble, I wouldn't be this nice. :-) I didn't mean a **web** service. I meant a small **Windows** service. Communicate between the two using either WCF or MSMQ (preferably WCF, hosted in the service). The communication would just pass the work to it. It could maintain a list or even MSMQ queue of completed requests. A separate AJAX call to the page would query the service to ask for status. Could be simpler if all you need is a working/done/error status, and not details.
John Saunders
I'll take that as an answer ;p. Thanks a lot!
Maxime
A: 

For accessing data:

For data like Server.Identity.Name, I think collecting that information beforehand and passing it to your async code is a good approach. Its good decoupling as that code now only depends on those few properties.

For accessing behavior:

How are you using threads with ASP.NET? The two approaches that work are to implement and register IAsyncHttpHandler, or you're call Page.AddOnPreRenderCompleteAsync() from some ASP.NET page.

For IAsyncHttpHandler, the callback you implement is passed an HttpContext. You should be able to use that referenced context from any thread until you indicate to ASP.NET that request processing has finished. Of course you should only use that reference from one thread a time.

For Page.AddOnPreRenderCompleteAsync, it should be safe to call Page.Context from your callbacks under the same conditions.

For the existing code you have in App_Code that uses HttpContext.Current, you need to refactor that so the code takes the HttpContext as an input parameter. Existing code can pass in HttpContext.Current, new code you're writing from threads can pass in one of the contexts described earlier in this answer.

Frank Schwieterman
It's IHttpAsyncHandler.
Anton