Pass data using ThreadLocal<T> across different classes - c#

Edited my Question with more info below regarding the "another thread" after usr pointed out that my question wasn't clear.
How can I pass data using the ThreadLocal<T> across different classes?
Basically, I need to pass the LogContext info from a class in the Webservice to a TraceExtension:SoapExtension class (The TraceExtension is to log request/responses of another WebService that this WebService calls).
Since the functionality runs on another thread and not the thread that initiated the request, I cannot get it from a ServiceContext:IExtension <InstanceContext>
, that I would normally use for such a thing.
I have a working implementation using the Thread.GetNamedDataSlot() way, but in performance testing we found there is a memory leak problem. (Yes, I have called the Thread.FreeNamedDataSlot() and the problem persisted). This lead to MS post http://support.microsoft.com/kb/2540745 that a leak problem may exist, but in our current timeframe for the release it will not be possible to deploy the fix on all the production servers. The work around suggested is to use the System.Threading.ThreadLocal class.
All the resources/examples I have found so far have instances of ThreadLocal in the same class and of Parallelism and PLinq. An example of initializing/setting data in one class and retrieving it from another will be very helpful.
Any other way of passing data to the TraceExtension : SoapExtension will also be equally helpful.
We are a bit tight on schedule and any help will be much appreciated.
Edit with more info:
The thread of our Webservice on which the request comes creates a new Thread on which we run some background processing, while returning the necessary response.
The new Thread invokes calls to other backend web services. We also have a TraceExtension class to trace the Request/Response to the backend web serivces.
We pass the LogContext info from the original Thread to the method on the new Thread using a ContextInfo : ISynchronizeInvoke.
The problem is getting the LogContext object From the class invoking the backend webservice call To the TraceExtension class (which runs on the new Thread and not the original Thread on which the client request came having the ServiceContext:IExtension<InstanceContext> which does hold the LogContext)

You want the ThreadStaticAttribute.

Related

How to know if HttpWebClientProtocol class is Thread Safe?

I read this question, but the answers and discussions are confusing myself.
So I decided to check, but how could I do it? How to create a test to prove if HttpWebClientProtocol class is Thread Safeor not?
I have already done the following test:
Create one HttpWebClientProtocol to call a WS.
I create the WS by myself and have just a Thread.Sleep(30000) inside.
So I create two independent threads to call this HttpWebClientProtocol at the same time.
The result is: Both threads called the WS with no problems. (One thread didn't need to wait the first call ends)
with this test have I proved that the object IS Thread Safe and the "correct' answer of the other question is wrong??
Well... I have a better test for you.
HttpWebClientProtocol Class
Directly from MSDN. Here's a copy/pasta of what they have to say about thread safety:
Thread Safety
The properties on this class are copied into a new instance of a WebRequest object for each XML Web service method call. While you can call XML Web service methods on the same WebClientProtocol instance from different threads at the same time, there is no synchronization done to ensure that a consistent snapshot of the properties gets transferred to the WebRequest object. Therefore, if you need to modify the properties and make concurrent method calls from different threads you should use a different instance of the XML Web service proxy or provide your own synchronization.
About thread safety
It's not about just "being available". But it's about making sure that data/state being affected by one thread does not affect the correct execution of the other thread.
If they share data structure and those structure are shared between threads, they are not thread-safe. The issue might not be easily apparent but on a system with large amount of usage of that class in a multi-threaded system, you could find some bugs/exceptions/weird behaviors that you will not be able to reproduce in a development environment and "only happens in production".
That my friend, is NOT thread safe.
About HttpWebClientProtocol and why it's not thread-safe
While the documentation is clear about being able to reuse the HttpWebClientProtocol, it is important to know that all the properties of the object itself are not going to be persisted to other requests created on another thread.
Meaning that if you have 2 threads playing with the Credentials property, you might end-up with some requests with different credentials. This would be bad in a web application with impersonation where requests could be done with a different credential and you could end-up with the data of someone else.
However, if you only need to set the initial properties once, then yes. You can reuse the instance.

Call from Web API to another Web API without waiting for results

Is there a way to fire an Http call to an external web API within my own web API without having to wait for results?
The scenario I have is that I really don't care whether or not the call succeeds and I don't need the results of that query.
I'm currently doing something like this within one of my web API methods:
var client = new HttpClient() { BaseAddress = someOtherApiAddress };
client.PostAsync("DoSomething", null);
I cannot put this piece of code within a using statement because the call doesn't go through in that case. I also don't want to call .Result() on the task because I don't want to wait for the query to finish.
I'm trying to understand the implications of doing something like this. I read all over that this is really dangerous, but I'm not sure why. What happens for example when my initial query ends. Will IIS dispose the thread and the client object, and can this cause problems at the other end of the query?
Is there a way to fire an Http call to an external web API within my own web API without having to wait for results?
Yes. It's called fire and forget. However, it seems like you already have discovered it.
I'm trying to understand the implications of doing something like this
In one of the links in the answers you linked above state the three risks:
An unhandled exception in a thread not associated with a request will take down the process. This occurs even if you have a handler setup via the Application_Error method.
This means that any exception thrown in your application or in the receiving application won't be caught (There are methods to get past this)
If you run your site in a Web Farm, you could end up with multiple instances of your app that all attempt to run the same task at the same time. A little more challenging to deal with than the first item, but still not too hard. One typical approach is to use a resource common to all the servers, such as the database, as a synchronization mechanism to coordinate tasks.
You could have multiple fire-and forget calls when you mean to have just one.
The AppDomain your site runs in can go down for a number of reasons and take down your background task with it. This could corrupt data if it happens in the middle of your code execution.
Here is the danger. Should your AppDomain go down, it may corrupt the data that is being sent to the other API causing strange behavior at the other end.
I'm trying to understand the implications of doing something like
this. I read all over that this is really dangerous
Dangerous is relative. If you execute something that you don't care at all if it completes or not, then you shouldn't care at all if IIS decides to recycle your app while it's executing either, should you? The thing you'll need to keep in mind is that offloading work without registration might also cause the entire process to terminate.
Will IIS dispose the thread and the client object?
IIS can recycle the AppDomain, causing your thread to abnormally abort. Will it do so depends on many factors, such as how recycling is defined in your IIS, and if you're doing any other operations which may cause a recycle.
In many off his posts, Stephan Cleary tries to convey the point that offloading work without registering it with ASP.NET is dangerous and may cause undesirable side effects, for all the reason you've read. That's also why there are libraries such as AspNetBackgroundTasks or using Hangfire for that matter.
The thing you should most worry about is a thread which isn't associated with a request can cause your entire process to terminate:
An unhandled exception in a thread not associated with a request will
take down the process. This occurs even if you have a handler setup
via the Application_Error method.
Yes, there are a few ways to fire-and-forget a "task" or piece of work without needing confirmation. I've used Hangfire and it has worked well for me.
The dangers, from what I understand, are that an exception in a fire-and-forget thread could bring down your entire IIS process.
See this excellent link about it.

Restrict requests made by Visual Studio generated soap client to single thread

I am testing a SOAP service using a client generated in VS2010 via "Add Service Reference".
I am running tests in parallel (c. 10 threads) and this has exposed some DB locking issues in the system under test. However, this is not going to be fixed straight away and I don't want my functional tests failing due to this problem.
As a result I have reduced by test threads to 1, and as expected I do not see the locking issue, however, this obviously makes my test suites a great deal slower. Therefore I was wondering if it is possible to use client configuration to restrict the client to only make one request concurrently?
Its not the soap client that needs to be restricted its the calling code. A Soap call will be performed in which ever thread it is being made from. If you have a problem with multiple threads this is because you have multiple threads in your code, or you are trying to make additional service calls or updating something in a callbacks without understanding what thread you are in.
Depending on the problem you have many solutions which could include:
Remove the multi-threading from your application, don't use callbacks and don't fire up additional threads.
or ideally Make sure you dispatch back to the UI when appropriate, understand which thread you are in so you fix the underlying locking problem
http://msdn.microsoft.com/en-us/library/ms591206.aspx
Me.Dispatcher.BeginInvoke(Sub()
' This will be executed on the UI Thread
End Sub)
It would be nice (and very useful) to have the code in question..... in your question. Which version of .net your using and what your app is written in (Asp.net, WinForms?) would also help get some context.
NB: Sample code in vb.net but you get the idea ;p

Thread pool use in .NET REST service implementation

I am implementing my first REST service in .NET 4 and have encountered something unexpected. It seems that I do not understand the underlining workings of Microsoft's ServiceModel, but could not find the answer in the traditional way.
To implement my web service I was following the steps in this tutorial: http://blogs.msdn.com/b/endpoint/archive/2010/01/06/introducing-wcf-webhttp-services-in-net-4.aspx
The service works. What surprised me was that Application_BeginRequest and Application_EndRequest in Global.asax are called by different threads. Looking at stack trace it appears that these threads are based in some kind of thread pool.
Without doing some refactorings this is a problem for us since we were always assuming that a single request would always run on the same thread, due to which we were keeping some variables stored in the thread local storage. The variables are initialized in Application_BeginRequest and released in Application_EndRequest. It appears that with ServiceModel this is not the right approach.
My questions are:
Can I make any assumptions about which threads are running my code when I am using ServiceModel?
Is there any way to restrict the execution to a single thread? Would this be bad for any reason?
What is the right way of storing a variable for the duration of request when using ServiceModel?
Thank you.
One thing I'd suggest is to consider using the WCF hooks rather than the Application_BeginRequest and Application_EndRequest methods. Four instance, here are four of the more useful hooks:
AfterReceiveRequest -> BeforeCall -> Method call -> AfterCall -> BeforeSendReply
There hooks are pretty powerful. You an inspect parameters before your method is called (centralize some logging to one place) and do all sorts of other useful things. These are not the only hooks available, there are some others I use as well. For instance GetInstance allows me to override creation of the service class object (so you can use dependency injection frameworks, etc).
When I use the per call concurrency mode, these hooks plus the method call itself ALL get called on the same thread. Hope this helps. I can provide links to implementing these hooks if you like.
Cheers
You may want to look at the [ServiceBehavior] attribute on your service implementation, since it supports arguments to control how many instances get created and what threading model is used.
http://msdn.microsoft.com/en-us/library/cc681240.aspx
When you have
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyService : IMyService
your service will run as a singleton but with multiple threads--up to a threshold set in the WCF config--calling into your methods. To force it to run on only one thread and thereby serialize inbound requests, set ConcurrencyMode.Single.
Alternatively, you could spin up a new instance of your service for each call:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Single)]
public class MyService : IMyService
The instance will have only one thread accessing it. In fact, when you have InstanceContextMode.PerCall, then the ConcurrencyMode is ignored because it's always "Single", and each instance is running in its own thread.

Do I need to dispose a web service reference in ASP.NET?

Does the garbage collector clean up web service references or do I need to call dispose on the service reference after I'm finished calling whatever method I call?
Instead of worrying about disposing your web services, you could keep only a single instance of each web service, using a singleton pattern. Web services are stateless, so they can safely be shared between connections and threads on a web server.
Here is an example of a Web Service class you can use to hold references to your web service instances. This singleton is lazy and thread-safe. It is advised that if you make your singletons lazy, they are also kept thread safe by following the same logic. To learn more about how to do this, read the C# In Depth article on Implementing Singletons.
Also keep in mind that you may run into issues with WCF web services. I'd recommend reading up on WCF's instance management techniques article, specifically the singleton section, for more details.
public static class WS
{
private static object sync = new object();
private static MyWebService _MyWebServiceInstance;
public static MyWebService MyWebServiceInstance
{
get
{
if (_MyWebServiceInstance == null)
{
lock (sync)
{
if (_MyWebServiceInstance == null)
{
_MyWebServiceInstance= new MyWebService();
}
}
}
return _MyWebServiceInstance;
}
}
}
And then when you need to access your web service, you can do this:
WS.MyWebServiceInstance.MyMethod(...)
or
var ws = WS.MyWebServiceInstance;
ws.MyMethod(...)
I've successfully used this pattern on several projects and it has worked well, but as tvanfosson mentions in the comments below, an even better strategy would be to use a DI framework to manage your web service instances.
I think the DataService inherits Dispose from Component.
Objects that implement IDispose should be disposed of manually to assist the garbage collector.
If you object is short lived use a using block. For objects that can be retained ensure that they object that retains them disposes of them when it is also disposed.
what are you trying to accomplish here?
If your worried about performance, then I would worry more about the responsiveness of the server hosting the webservice and the network speed, as they can dramatically affect the length of time you have to wait for the webservice call to complete (unless its asynchronous).
The examples on MSDN dont call 'Dispose' and its quite obvious that the garbage collector will do its job, so unless your working on a realtime system that needs to process over 100,000 records in memory every second, then maybe you dont need to come up with a way to dispose resources or manage memory.
I think the concerns of Seabizkit in the above answer are very legitimate.
It's quoted here:
#DanHerbert what happens when two threads call the singleton.. let me explain... there is a lock on the object.. to make it thread safe. Does that mean that if theard1 call accesses webInstance, then thread2 will wait on thread1 to finish. or is the lock purely for the creatation of the instance. say you have 10 callers.... does the lock mean they are chained... or async, i think you will get what I'm asking let me know if it wasn't clear. – Seabizkit Oct 13 '16 at 10:01
<
After I've done some testing I can tell that you won't be able to get any good performance when a single 'client' object is used by multiple different threads.
If ten threads are created and they all are using the same singleton 'client' then they will have to wait in line until all previous calls are done.
To see the proof for that please read and run a sample in this c-sharp corner article here:
https://www.c-sharpcorner.com/article/increase-performance-with-an-object-pool-or-why-singleton-may-cause-performance/
titled "Increase Performance with an Object Pool or Why Singleton May Cause Performance Issues".
Sorry to burst the bubble of the singleton web service users. Also, you would be very hard-pressed to find Microsoft's example where the web service client is "caged" in the singleton.

Categories

Resources