Showing posts with label Thread Safety. Show all posts
Showing posts with label Thread Safety. Show all posts

Wednesday, May 4, 2016

IResourceLoader: Balancing Semaphores

Recently I need to get balance getting resources from a restricted number of sources. So, for example...

I am getting resource R, and I have factories A, B and C creating those Rs. Each of those factories has a very limited capacity for creating those resources, and can only create two Rs at a time. It is easy to put the factories behind a semaphore and limit how many threads can be requesting resources from each factory at a time.

The challenge is evenly balancing the workload between all three factories. Also, please note that you can't just round robin the semaphores because there is no way to ensure that each operation will complete in the same amount of time.

To do this I created a generic IResourceLoader interface, and made two implementations: one to wrap a semaphore, and the other to wrap and balance a collection of IResourceLoaders. Below is the implementation, complete with unit tests; let's take a look!

Interface

public interface IResourceLoader<T>
{
    int Available { get; }
    int Count { get; }
    int MaxConcurrency { get; }
 
    Task<T> GetAsync(CancellationToken cancelToken = default(CancellationToken));
    bool TryGet(out Task<T> resource, CancellationToken cancelToken = default(CancellationToken));
}

Saturday, October 31, 2015

How to change HttpClientHandler.AllowAutoRedirect

In the past I have talked about how the HttpClient is thread safe. This allows you to reuse the same HttpClient and be very efficient regarding how many ephemeral ports your application consumes.

Because the HttpClient and the HttpClientHandler both need to be thread safe, their properties become immutable after a request has been issued. If you are in a scenario where you need to change settings, such as whether or not the handler allows redirects, you will have to develop a little hack to work around the default behavior.

Below is a method where you can use reflection to set a private field and avoid the property setter from checking whether or not a request has been issued. This could cause thread safety issues, however with the current implementation of HttpCliehtHandler it is perfectly safe so long as only one thread is consume the client at a time.

HttpClientHandler Extension

public static class HttpClientHandlerExtensions
{
    private static readonly FieldInfo AllowAutoRedirectFieldInfo =
        typeof (HttpClientHandler).GetField(
            "allowAutoRedirect",
            BindingFlags.Instance | BindingFlags.NonPublic);
 
    public static void SetAllowAutoRedirect(this HttpClientHandler handler, bool value)
    {
        AllowAutoRedirectFieldInfo.SetValue(handler, value);
    }
}

Unit Test

public class HttpClientHandlerExtensionsTests
{
    [Fact]
    public async Task SetAllowAutoRedirectTest()
    {
        using (var handler = new HttpClientHandler())
        using (var client = new HttpClient(handler))
        {
            handler.AllowAutoRedirect = true;
 
            using (var response = await client.GetAsync("http://www.google.com"))
                response.EnsureSuccessStatusCode();
 
            Assert.Throws<InvalidOperationException>(() =>
            {
                handler.AllowAutoRedirect = false;
            });
 
            handler.SetAllowAutoRedirect(false);
        }
    }
}

Enjoy,
Tom

Saturday, November 29, 2014

.NET 4.5 HttpClient is Thread Safe

Good news everyone, the .NET 4.5 HttpClient is thread safe!

This means that you can share instances of your HttpClients across your entire application. This is useful in that it allows you to reuse persisted connections. One of the best ways to do this is to create a class that can manage the object lifetime of those clients for you.

Below is a simple HttpClientManager that will create one HttpClient per authority. Why per authority? Because you might have to have different settings or credentials for different websites.

Sample Unit Tests

public class HttpClientManagerTests
{
    [Fact]
    public void GetForAuthority()
    {
        using (var manager = new HttpClientManager())
        {
            var client1 = manager.GetForAuthority("http://tomdupont.net/");
            var client2 = manager.GetForAuthority("https://tomdupont.net/");
            Assert.Same(client1, client2);
 
            var client3 = manager.GetForAuthority("http://google.com/");
            Assert.NotSame(client1, client3);
        }
    }
 
    [Fact]
    public void TryRemoveForAuthority()
    {
        const string uri = "http://tomdupont.net/";
 
        using (var manager = new HttpClientManager())
        {
            Assert.False(manager.TryRemoveForAuthority(uri));
 
            manager.GetForAuthority(uri);
 
            Assert.True(manager.TryRemoveForAuthority(uri));
 
        }
    }
}

Saturday, December 7, 2013

ConcurrentDictionary.GetOrAdd and Thread Safety

.NET 4.0 added the awesome System.Collections.Concurrent namespace, which includes the very useful ConcurrentDictionary class. While the ConcurrentDictionary is thread safe, it can experience problems with adding values during high concurrency...

ConcurrentDictionary.GetOrAdd may invoke the valueFactory multiple times per key.

This behavior will only happens under high load, and even if the valueFactory does get invoked multiple times the dictionary entry will only ever be set once. Normally this is not much of a problem. However, if you are using this Dictionary to store large or expensive objects (such as unmanaged resources or database connections), then the accidental instantiation of multiple of these could be a real problem for your application.

Don't worry, there is a very simple solution to avoid this problem: just create Lazy wrappers for your expensive objects. That way it will not matter how many times the valueFactory is called, because only one instance of the resource itself will ever actually be accessed and instantiated.

Real Time Web Analytics