Passing data between ThreadPool threads - c#

I have a C# webserver which I have been profiling using the StackOverflow miniprofiler. Because it's not an ASP.NET server, but each request was typically executed on its own thread, I rigged the miniprofiler to use ThreadStatic storage to track all of the profilers of an incoming request from start to finish. This worked well.
Recently we've converted everything to use async/await, which means continuations after an await typically don't come back onto the same Thread and thus the ThreadStatic storage no longer works.
What's the best way to pass some small piece of data between different ThreadPool threads in this case? Are there existing SynchronizationContext implementations that would be useful for something like this?

What's the best way to pass some small piece of data between different ThreadPool threads in this case?
Using the logical call context via the CallContext class. It exposes two static methods: LogicalSetData and LogicalGetData. The call context is stored and marshaled via the ExecutionContext, which is also in charge of the sync context, etc.
Using this class has two restrictions:
You're limited to the use of .NET 4.5 and above
Logical call context uses copy-on-write semantics, and performs a shallow copy once the data is mutated. This means you should only be using immutable data, as the references may be shared across multiple threads.
One last thing to note is CallContext is initialized only once you call it. This means that when using it, you're taking on some overhead because of the copy-on-write.
More on that can be found in a post by Stephan Cleary called Implicit Async Context

Related

Trying to multithread using a global udpclient object, is there possible collisions issues?

I'm making a project in a p2p sharing system which will initiate a lot of sockets with the same ports. right now I'm using a global UdpClient which will use receive and sendasync methods on different threads with different endpoints. there is no usage of mutex as of now which is why I'm asking if collisions are possible using said object if I'm not changing the information inside this object
right now I tried only one example and it doesn't seem to collide although I don't trust one example enough for a full answer
As far as I can see, UdpClient is not thread safe. Thread safe objects should specifically mention that in the documentation, and UdpClient does not seem to do that.
So without any type of synchronization your code is most likely not safe. Testing is not sufficient since multi threading bugs are notorious for being difficult to reproduce. When you write multi threaded code you need to ensure any shared data is synchronized appropriately.
Using it within a lock is probably safe. But that is not a guarantee, UI objects are only safe to use from the thread that created the. Unfortunately that is not always well documented. A problem with locks is that it will block the thread, so locks are best used for very short and fast sections of code, not while doing long running operations like IO. And I don't think the compiler will even let you hold a lock while awaiting.
Another pattern is to use one or more concurrent queues, i.e. threads put messages on the queue, and another thread reads from the queue and sends the messages. There are many possible designs, and the best design will really depend on the specific application. However, designing concurrent systems is difficult, and I would recommend trying to create modules that are fairly independent, so you can understand and test a single module, without having to understand the entire program.
Memory is safe read concurrently. But the same does not extend to objects, since many object may mutate internal state when reading. Some types, like List<T>, specifically mentions that concurrent reads are safe. So make sure you check the documentation before using any object concurrently.

Async when continuing on another thread

I know that a Task may continue the execution on another thread, proven by this code.
public async Task Test()
{
var id1 = System.Environment.CurrentManagedThreadId;
await Task.Delay(1000);
var id2 = System.Environment.CurrentManagedThreadId;
Console.Write($"First {id1} then {id2}");
}
I expect the framework to handle memory barrieres, so that id1 is visible when accessed in the last statement.
But what if you are using some kind of framework e.g. NHibernate where the ISession is not thread safe. Frameworks may even check that the thread ID is still the same. How does this mix?
When building website, I'll to use a IOC container with a nested container per request, but when then thread could change within the same request, wouldn't this lead to all kind of problems? ThreadStatic would not work as expected
Not being thread safe usually means don't use it from multiple threads at the same time, rather than don't use it from one thread and then from another thread later.
I don't know about NHibernate specifically, but if it's a problem, consider using EF Core.
In general with async, don't use variables attached to specific threads, like thread local or thread static.
However, local variables, class members, logical call contexts, HttpContext if you're on asp.net etc continue to work. If you do have something that will be lost after an await, you can usually just save it to a local variable first.
The default ConfigureAwait(true) also restores some context on the continuation, but it can be hard to know what is restored and what isn't. Later versions of .net do a better job of this, like restoring the culture so that resources keep working after an await.
There's a good article by Stephen Toub here:
https://blogs.msdn.microsoft.com/pfxteam/2012/06/15/executioncontext-vs-synchronizationcontext/

HttpClient provide not truly async operations?

I'm confused about async IO operations. In this article Stephen Cleary explains that we should not use Task.Run(() => SomeIoMethod()) because truly async operations should use
standard P/Invoke asynchronous I/O system in .NET
http://blog.stephencleary.com/2013/11/there-is-no-thread.html
However, avoid “fake asynchrony” in libraries. Fake asynchrony is when
a component has an async-ready API, but it’s implemented by just
wrapping the synchronous API within a thread pool thread. That is
counterproductive to scalability on ASP.NET. One prominent example of
fake asynchrony is Newtonsoft JSON.NET, an otherwise excellent
library. It’s best to not call the (fake) asynchronous versions for
serializing JSON; just call the synchronous versions instead. A
trickier example of fake asynchrony is the BCL file streams. When a
file stream is opened, it must be explicitly opened for asynchronous
access; otherwise, it will use fake asynchrony, synchronously blocking
a thread pool thread on the file reads and writes.
And he advises to use HttpClient but internaly it use Task.Factory.StartNew()
Does this mean that HttpClient provides not truly async operations?
Does this mean that HttpClient provides not truly async operations?
Sort of. HttpClient is in an unusual position, since it's primary implementation uses HttpWebRequest, which is only partially asynchronous.
In particular, the DNS lookup is synchronous, and I think maybe the proxy resolution, too. After that, it's all asynchronous. So, for most scenarios, the DNS is fast (usually cached) and there isn't a proxy, so it acts asynchronously. Unfortunately, there are enough scenarios (particularly from within corporate networks) where the synchronous operations can cause significant lag.
So, when the team was writing HttpClient, they had three options:
Fix HttpWebRequest (and friends) allowing for fully-asynchronous operations. Unfortunately, this would have broken a fair amount of code. Due to the way inheritance is used as extension points in these objects, adding asynchronous methods would be backwards-incompatible.
Write their own HttpWebRequest equivalent. Unfortunately, this would take a lot of work and they'd lose all the interoperability with existing WebRequest-related code.
Queue requests to the thread pool to avoid the worst-case scenario (blocking synchronous code on the UI thread). Unfortunately, this has the side effects of degrading scalability on ASP.NET, being dependent on a free thread pool thread, and incurring the worst-case scenario cost even for best-case scenarios.
In an ideal world (i.e., when we have infinite developer and tester time), I would prefer (2), but I understand why they chose (3).
On a side note, the code you posted shows a dangerous use of StartNew, which has actually caused problems due to its use of TaskScheduler.Current. This has been fixed in .NET Core - not sure when the fix will roll back into .NET Framework proper.
No, your assumptions are wrong.
StartNew isn't equal to the Run method.
This code is from HttpClientHandler, not the HttpClient, and you didn't examine the this.startRequest code from this class. The code you're inspecting is a prepare method, which starts a task in new thread pool, and inside call actual code to start an http request.
HTTP-connection is created not on the .NET level of abstraction, and I'm sure that inside startRequest you'LL find some P/Invoke method, which will do actual work for:
DNS lookup
Socket connection
Sending the request
waiting for the answer
etc.
As you can see, all above are logic which really should be called in async manner, because it is outside the .NET framework, and some operation can be very time-consuming. This is exactly logic that should be called asynchroniously, and during the waiting for it .NET thread is being released in ThreadPool to process other tasks.

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.

Multithreaded Service Engineering Questions

I am trying to leverage .NET 4.5 new threading capabilities to engineer a system to update a list of objects in memory.
I worked with multithreading years ago in Java and I fear that my skills have become stagnant, especially in the .NET region.
Basically, I have written a Feed abstract class and I inherit from that for each of my threads. The thread classes themselves are simple and run fine.
Each of these classes run endlessly, they block until an event occurs and it updates the List.
So the first question is, how might I keep the parent thread alive while these threads run? I've prevented this race condition by writing this currently in a dev console app with a Console.read().
Second, I would like to set up a repository of List objects that I can access from the parent thread. How would I update those Lists from the child thread and expose them to another system? Trying to avoid SQL. Shared memory?
I hope I've made this clear. I was hoping for something like this: Writing multithreaded methods using async/await in .Net 4.5
except, we need the adaptability of external classes and of course, we need to somehow expose those Lists.
You can run the "parent" thread in a while with some flag to stop it:
while(flag){
//run the thread
}
You can expose a public List as a property of some class to hold your data. Remember to lock access in multithreading code.
If the 'parent' thread is supposed to wait during the processing it could simply await the call(s) to the async method(s).
If it has to wait for specific events you could use a signaling object such as a Barrier.
If the thread has to 'do' things while waiting you could check the availability of the result or the progress: How to do progress reporting using Async/Await
If you're using tasks, you can use Tasks.WaitAll to wait for the tasks to complete. The default is that Tasks and async/await use your system's ThreadPool, so I'd avoid placing anything but relatively short running tasks here.
If you're using System.Threading.Thread (I prefer using these for long running threads), check out the accepted answer here: C# Waiting for multiple threads to finish
If you can fetch batches of data, you can expose services allowing access to the shared objects using self hosted Web API or something like NancyFX. WCF and remoting are also options if you prefer binary communication.
Shared memory, keep-alive TCP connections or UDP are options if you have many small transactions. Perhaps you could use ZeroMQ (it's not a traditional queue) with the C# binding they provide?
For concurrent access to the lists take a look at the classes in System.Collections.Concurrent before implementing your own locking.

Categories

Resources