In my asp.net (4.7.2) application sometimes occur thread hop. I have used HttpContext.Current to deal with it. But some ago AsyncLocal come, but I find out it is null after thread hop. Is it right behavior or I should use f.e. net 4.8?
update
Thread hop have another name - thread agility. The fenomen is described f.e in post:
What is the meaning of thread-agility in ASP.Net?
Related
I've read here https://blog.stephencleary.com/2009/10/synchronizationcontext-properties.html that ASP.NET applications' execution context does not have specific associated thread. Does it mean code after await will(can) be executed in different thread with the same context ? In this case how it is possible that deadlock can be caused by synchronous execution? Or ASP.NET application is not the case for such deadlock ?
Thanks in advance.
For ASP.NET Classic (.NET Framework), there is a special AspNetSynchronizationContext, the continuation will post back to the original context thread.
ASP.NET Core there isn’t one. If you inspect SynchronizationContext.Current you’ll find that it’s set to null. As such, a continuation is free to use what ever thread it chooses, and will suffer no classic deadlocks in that respect
Update
Some great corrections from #StephenCleary in the comments
Minor correction : on classic ASP.NET, the SynchronizationContext
represents the request context, not a specific thread.
The method may resume on any thread pool thread after the await.
The deadlock occurs because there is a lock as part of that request
context to ensure that only one thread at a time may be in the
request context.
So, when the async method is ready to resume, a thread pool thread
is taken which enters the request context and tries to take that
lock. If there's another thread blocked on that task in the context, the lock is already taken and a deadlock will occur
I've got a few instances of the same class. During the classes lifetime, every method call on this class should be executed on the same thread. But for each instance I need a different thread.
I thought about Threadpool, but it seems that I have too less control about it.
How can I reuse a thread without using ThredPool?
Thank you! Martin
Edit (why I need this):
I have to use a win32 dll to access business logic of a third-party product. This dll is not designed for a multi-threaded environment like a web application. When I run my ASP.NET MVC application in ASP Classic Mode (STA Thread), everything works fine so far. But the problem is that all users going to block each other. This component also maintains some state. As soon as a different thread is accessing this component, it will not recognize the connection-handle I have to pass in for each method call. I got the connection handle after a logon procedure. I want to put my web application in MTA mode back again and use a worker-concept, assigning about 10 users to a worker (max. 10 users should block each other). One worker should always use the same thread to execute the api calls so the component will not stubmle.
I'm not happy with this situation, but I have to find am acceptable solution.
Update - Found a Solution:
Thanks to the "Smart Thread Pool" from Ami Bar I could accomplish the behavior I was looking for (easily). For each worker, I have now my own thread pool instance with a max and min number of one thread. Well, it's not the idea of a thread pool, but it makes it very easy to handle the work-items and it also has some nice other featrues. The web application is running on MTA now.
I'm going to prepare some load tests to see if its stable over hours.
see here: http://www.codeproject.com/Articles/7933/Smart-Thread-Pool
When calling BeginInvoke on a delegate, the action is executed on a separate thread. If called in ASP.NET does it use a CLR worker thread? Or does it use an IIS worker thread?
If the latter, then I will need to employ an asynchronous ASP.NET pattern to ensure the action is executed on a CLR worker thread. But I would rather not do that if the action ends up there upon BeginInvoke.
it uses a CLR worker thread.
as described in here
To begin with, ASP.NET uses the process-wide CLR thread pool to service requests (for more background on the CLR thread pool, see the .NET column in this issue).
EDIT:
another resource is this blog
Unfortunately, the thread used by BeginInvoke is actually taken from the same worker thread pool that is used by ASP.Net to handle Page Requests
Thread usage/management is a bit different in IIS6, IIS7 and IIS 7.5.
Pretty detail and updated explanation here:
ASP.NET Thread Usage on IIS 7.5, IIS 7.0, and IIS 6.0
Not sure if this answers your question but a good read anyways.
Using a custom delegate and calling its BeginInvoke method offer a quick way to fire off worker threads for your application. But unfortunately, they hurt the overall performance of your application since they consume threads from the same pool used by ASP.NET to handle HTTP requests.
Just remember too, if the callback from the Asynchronous method is important then, you need to block the main thread from returning to the client until the asynchronous process has completed. If the logging and analytics is a 'fire-and-forget' method call, then things are easier and you can just fire off the method and allow the server to respond to the client. However, if the callback is important and the server has completed processing, nothing is happening on the server to handle the callback once completed; this is where asynchronous processing on the server for ASP.NET applications differs from say a WinForms application.
(asp.net 2.0, C#)
I need to implement threading that will be:
Attributable to the user that started the thread (e.g. on a callback, I could use an ID or the name of a thread to look up the thread that the user previously started).
If the thread is finished, the callback should be able to look up the thread and know it is finished.
Finally, the thread would need to automatically terminate if it is active for, say, more than a minute.
I've read quite a bit and I now know that I need to personally manage the threads (e.g. I can't use the asp.net thread pool) because of requirement (1) I listed above. I notice that the Thread class in C# has an ID property; can that ID be used to implement requirement (1) (I don't know if that ID will always be unique, etc)?
Btw, I understand that asp.net can terminate threads at certain points. Basically, any time the user's Session is wiped out, my thread is useless anyway. If the thread does fail or does get terminated for whatever reason, that's fine because the task will be restarted. Mostly I'm concerned with finding some way where the user can look up the thread that was started .. can this be accomplished by storing the ID property in Session? Also, if so, how do I go about using that property to actually find the thread? If not, what is the recommended way to do what I'm asking. Thanks.
IIS will identify the ASP.Net threads for you. You don't need to manage threads on your own. You may need to adjust your authentication method (link 1) or explicty place an IPrincipal object into HttpContext.User (link 2)
IIS Blog
MSDN article
What are differences between CallContext and ThreadStatic?
I've understood that in an ASP.NET environment data stored in CallContext could be persisted throughout the request until it ends while ThreadStatic may or may not work since the request may switch threads. I've also learned that the HttpContext is internally stored using the CallContext.
In a regular application they both seem to persist throughout the same thread call. When isn't this the case?
Edit: In the comments I learned that the call context is an abstraction over a thread static store. The ASP.NET framework explicitly moves the data from one thread to the next that is to handle one request. Other framework that wants to provide thread agility could do the same to for contextual storage.
Very often a request will use the same thread throughout, but it certainly won't always be the case - ASP.NET exhibits thread agility. There's an old in-depth blog article about the matter from 2005, but as of .NET 4.5 things are rather better.
Items stored as ThreadStatic are available to more than one request. IIS reuses the thread after a request is complete to process subsequent requests, it can even swap a request from one thread to another during processing. ASP.Net clears down the CallContext after each request.