I have the need to have an option to enabled deep debug logging using log4net. I am familiar with how classic ASP.Net handles threads, but I wondered how threads work with ServiceStack. The goal would be to use %Thread to group requests together in the log. I think the only problem is that there is likely a thread pool and the %thread id will be reused on subsequent requests.
Really what I am looking for is a single unique id I can expose to log4net so I can group the entire logging of a single request together when building a report.
Can anyone lend some guidance?
See this page on concurrency in ServiceStack, i.e. ServiceStack when hosted in ASP.NET doesn't create any new threads itself, requests are simply handled on the same IIS/Nginx/etc ASP.NET HTTP WebWorker that handles the request. Ultimately control of the Thread Pool and thread instances is up to the underlying ASP.NET but its common for them to re-use the same threads to handle different requests.
Use IHttpRequest.Items whenever you want to share any data throughout the lifetime of a single request, e.g. you could simply assign a Guid at the start of the request using a PreRequestFilters with:
this.PreRequestFilters.Add((req, res) => req.Items["ReqId"] => Guid.NewGuid());
Which lasts the entire lifetime of the request and the same instance of IHttpRequest is available in all filters, services, views, etc.
Related
I have a web method in an ASP.NET site that could run long and consume a lot of CPU capacity. It is also possible that, before a request is returned, the user could fire a new request with other or more parameters from the site. On the client side a do an abort:
if (xhrConfigurate != null) {
xhrConfigurate.abort();
}
Of course, abort will not stop the calculations on the server. I tought, this is ok, the server will do what it have to do, but will not return the results of the old requests. But it seems that in some cases, the server has troubles to handle all requests in a timely matter.
That is why I also want to kill the old requests when a user launches a new one. I have found some solutions with scriptmanager, but would like to avoid using that.
As the webmethod itself is a asynchronous thread, can't I get an instance of this thread, store it in some dictionary where I can abort the old not finished requests for a user and remove a request when it is finished?
<WebMethod> Public Shared Function myRequest(ByVal params As String) As String
'Get the dictionary with requests
'Test the dictionary on old unfinsihed request for the user, if there is one: abort
'Add this request to the dictionary
'Do work...
'If work finsihed: remove this request from dictionary
Return result
End Sub
If I understand correctly, you want to have some global variable dictionary with requests queue, so that any web method execution would share same dictionary?
Using global variable is tricky thing, IIS application pool may restart anytime. Somewhere I read, it's recycling automatically every 24 or 29 hours on IIS. So global variable values might be lost.
Thread related to the problem:
What exactly is Appdomain recycling
I have ASP WebApi service, and I have similar long running tasks. I host ASP application in console app (host) (no IIS!), and I use ObservableCollection variable to store requests in AppDomain.
Then each requests thread can access that collection safely (if I am not mistaken).
In general, it is a bad idea to run a long-running process inside of ASP.NET. Instead, you should create a separate server process, and your ASP.NET code should queue a request to that process.
Your server could return a unique value back to ASP.NET, which could then send that value back to the web page. When the user makes a request, you would pass that value to ASP.NET, which would pass it to the service. The service could determine whether there is already a request running with that unique value and, if there is, the service could abort that thread.
I have a WCF service with ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple). I want to use ThreadStatic variable to srore data.
I start worrying about is it possible two parallel requests for the same or different operationContracts get handled by the same thread serverside, because if this happens my ThreadStatic variable will get overriden.(I.e. something like the thread changing between HttpHandlers and HttpModules in ASP.NET)
I made a spike service with the same ServiceBehaviour and maxConcurrentCalls="2". After that a wcf client called the service with 50 parallel requests and my worry did not occur. However this is not a 100% proof.
Thank in advance!
Irrespective of the ConcurrencyMode, a ThreadStatic value will persist when your request terminates and the thread is returned to the thread pool. The same thread can be reused for a subsequent request, which will therefore be able to see your ThreadStatic value.
Obviously this won't be true for two concurrent requests, because by definition they will be executed on different threads.
From comments:
Also by definition MSDN says: 'The service instance is multi-threaded. No synchronization guarantees are made. Because other threads can change your service object at any time, you must handle synchronization and state consistency at all times.' So it is not so obvious:)
This means that a single instance of your service class can be accessed concurrently by multiple requests. So you would need to handle synchronization for any accesses to instance members of the service class.
However ThreadStatic members are by definition only used by one thread (and hence one request) at a time, so don't need synchronization.
The direct answer to your question is Joe's answer.
However you mention in the comments you are using an ambient design pattern. That pattern is already implemented in WCF as the OperationContext and is specifically designed to be extensible. I highly recommend using OperationContext over any custom thread storage.
See Where to store data for current WCF call? Is ThreadStatic safe?
I wanted to add to Joe's answer here because I would recommend that you use some sort of correlation for your requests if you're needing to store state. The threading model will become very convoluted and unreliable in production.
Further, now imagine you have two IIS servers hosting this service and a hardware or software load balancer forward facing so that you can consume it. To ensure that the correct state is gathered you'll need correlation because you never know which server the service will be started on. In the post below I mocked up a simplified version of how that might work. One thing to keep in mind is that the SessionState would need to be kept in a shared location to all instances of the service, an AppFabric Cache server for example.
Global Variable between two WCF Methods
how to handle multiple http requests from a single client such that it is handled by single Asp.net thread. When PageAsyncTask or TPL is not an option as it does create a new thread. Code snipet will be of great help.
Each separate HTTP request will be executed on a potentially separate thread.
You have no control over which thread execution of your ASP.Net page is scheduled on.
I do not believe this can be accomplished.
Think about why you are trying to do this. Do you need to share some information between the various HTTP requests? If so, consider using a session or a cookie to manage that information.
I've just read this interesting article regarding simultaneously calling multiple methods on a WCF service from Silverlight:
http://weblogs.asp.net/olakarlsson/archive/2010/05/20/simultaneously-calling-multiple-methods-on-a-wcf-service-from-silverlight.aspx
The article states: "It turns out that the issue is founded in a mix of Silverlight, Asp.Net and WCF, basically if you’re doing multiple calls to a single WCF web-service and you have Asp.Net session state enabled, the calls will be executed sequentially by the service, hence any long running calls will block subsequent ones."
I am assuming that the blocking is only an issue if you are making multiple calls to the same service, and that two simultaneous calls to two different methods on two different services should not result in one blocking the other?
The suggested solution to the problem in SL3 involves using the following syntax in the Application_Startup method:
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
The session state will then have to be maintained on WCF calls by seting up a cookie container, and sharing it across all of your proxies (see http://forums.silverlight.net/forums/p/174322/393032.aspx)
Is this still the recommended solution in Silverlight 4? Has anyone used an alternative approach?
In .NET 4, you can do this in Application_BeginRequest
if (Context.Request.Path.EndsWith("xxx.svc"))
Context.SetSessionStateBehavior(SessionStateBehavior.Disabled);
If you are making a call into an ASP.Net application, and you are using session cookies, then all the calls into the application are serialized (apart from ones where the page explicitly opts out of session state).
Normally this isn't a big issue, because a client browser typically hits an ASP.Net page plus a bunch of resources (images, js, css etc...), and these latter aren't mapped to ASP.Net so IIS serves them up natively. But if you try and hit two ASP.Net pages at the same time (eg in a frameset) you will see them load up one after another.
Now I don't know that this happens with WCF, but based on what you say, if you see that behaviour for one service I would expect to see that for all of them, because the session is per-user, not per-service.
In ASP.Net you can 'opt out' of session state on a page by page basis. If that's possible for a hosted WCF service, and viable for your scenario (to make the services stateless) that would aleviate the issue. Or move one or more services to a different ASP.Net application (different session)
Bear in mind that you can see other issues here to do with the instancing and reentrancy models of the service. Your problem as described above is a per-user concurrency issue, but there are others. For example, if you set the service up as a singleton (InstanceContextMode.Single) and non-reentrant (ConcurrencyMode.Single) then only one request will ever be processed at a time across all users.
Update: Doing some doco reading:
WCF services aren't enrolled into ASP.Net sessions unless you ask for it (using )
WCF services can on a per service basis opt in, using the [AspNetCompatibilityRequirements] attribute on the service implementation
There doesn't seem to be any way of opting in but not opting into Session state.
There's a good blog post about this on Wenlong Dong's site
So from what I can see you should be able to use AspNetCompatibilityRequirementsMode.NotAllowed to opt out individual services completely from ASP.Net services. Alternatively, leave it off by default and only opt-in the ones that need access to the ASP.Net session (bearing in mind that unless you really need to share the same session with ASP.Net, just using WCF's session services is probably a better bet).
Recently, the book on threading for Winforms application (Concurrent programming on Windows by Joe Duffy) was released. This book, focused on winforms, is 1000 pages.
What gotchas are there in ASP.NET threading? I'm sure there are plenty of gotchas to be aware of when implementing threading in ASP.NET. What should I be aware of?
Thanks
Since each http request received by IIS is processed separately, on it's own thread anyway, the only issues you should have is if you kick off some long running process from within the scope of a single http request. In that case, I would put such code into a separate referenced dependant assembly, coded like a middle-tier component, with no dependance or coupling to the ASP.Net model at all, and handle whatever concurrency issues arose within that assembly separately, without worrying about the ASP.Net model at all...
Jeff Richter over at Wintellect has a library called PowerThreading. It is very useful if you are developing applications on .NET. => Power Threading Library
Check for his presentations online at various events.
Usually you are encouraged to use the thread pool in .Net because it of the many benefits of having things managed on your behalf.....but NOT in ASP.net.
Since ASP.net is already multi-threaded, it uses the thread pool to serve requests that are mapped to the ASP.net ISAPI filter, and since the thread pool is fixed in size, by using it you are basically taking threads away that are set aside to do the job of handling request.
In small, low-traffic websites, this is not an issue, but in larger, high-traffic websites you end up competing for and consuming threads that the ASP.net process relies on.
If you want to use threading, it is fine to do something like....
Thread thread = new Thread(threadStarter);
thread.IsBackground = true;
thread.Start();
but with a warning: be sure that the IsBackground is set to true because if it isn't the thread exists in the foreground and will likely prevent the IIS worker process from recycling or restarting.
First, are you talking about asynchronous ASP.NET? Or using the ThreadPool/spinning up your own threads?
If you aren't talking about asynchronous ASP.NET, the main question to answer is: what work would you be doing in the other threads and would the work be specific to a request/response cycle, or is it more about processing global tasks in the background?
EDIT
If you need to handle concurrent operations (a better term than multi-threaded IMO) for a given request/response cycle, then use the asynchronous features of ASP.NET. These provide an abstraction over IIS's support for concurrency, allowing the server to process other requests while the current request is waiting for work to complete.
For background processing of global tasks, I would not use ASP.NET at all. You should assume that IIS will recycle your AppPool at a random point in time. You also should not assume that IIS will run your AppPool on any sort of schedule. Any important background processing should be done outside of IIS, either as a scheduled task or a Windows Service. The approach I usually take is to have a Windows Service and a shared work-queue where the web-site can post work items. The queue can be a database table, a reliable message-based queue (MSMQ, etc), files on the file system, etc.
The immediate thing that comes to mind is, why would you "implement threading" in ASP.NET.
You do need to be conscious all the time that ASP.NET is multi-threaded since many requests can be processed simulatenously each in its own thread. So for example use of static fields needs to take threading into account.
However its rare that you would want to spin up a new thread in code yourself.
As far as the usual winforms issues with threading in the UI is concerned these issues are not present in ASP.NET. There is no window based message pump to worry about.
It is possible to create asynchronous pages in ASP.NET. These will perform all steps up to a certain point. These steps will include asynchronously fetching data, for instance. When all the asynchronous tasks have completed, the remainder of the page lifecycle will execute. In the meantime, a worker thread was not tied up waiting for database I/O to complete.
In this model, all extra threads are executing while the request, and the page instance, and all the controls, still exist. You have to be careful when starting your own threads, that, by the time the thread executes, it's possible that the request, page instance, and controls will have been Disposed.
Also, as usual, be certain that multiple threads will actually improve performance. Often, additional threads will make things worse.
The gotchas are pretty much the same as in any multithreaded application.
The classes involved in processing a request (Page, Controls, HttpContext.Current, ...) are specific to that request so don't need any special handling.
Similarly for any classes you instantiate as local variables or fields within these classes, and for access to Session.
But, as usual, you need to synchronize access to shared resources such as:
Static (C#) / Shared(VB.NET) references.
Singletons
External resources such as the file system
... etc...
I've seen threading bugs too often in ASP.NET apps, e.g. a singleton being used by multiple concurrent requests without synchronization, resulting in user A seeing user B's data.