[WP7] A nasty concurrency bug in the bundled Reactive Extensions

By Admin at April 21, 2011 20:05 Tags: , , , , ,

The Reactive Extensions have been included in Windows Phone 7, which comes out of the box, and that you can include the Microsoft.Phone.Reactive.dll assembly.

 

This is a good thing, because it participates in the democratization of the Rx framework, and aside from the fact that the namespace is not exactly the same as the desktop version, Microsoft.Phone.Reactive instead of System.Concurrency and System.Linq, there were no major bugs until recently.

A few applications I've worked on that use the Rx framework, a very interesting unhandled exception was popping-up from time to time in my exception tracker. Unlike the double tap issue I found the same way on my Remote Control application, that one was a bit more tricky, see for yourself :

Exception : System.NullReferenceException: NullReferenceException
at Microsoft.Phone.Reactive.CurrentThreadScheduler.Trampoline.Run()
at Microsoft.Phone.Reactive.CurrentThreadScheduler.EnsureTrampoline(Action action)
at Microsoft.Phone.Reactive.AnonymousObservable`1.Subscribe(IObserver`1 observer)
at Microsoft.Phone.Reactive.ObservableExtensions.Subscribe[TSource](IObservable`1 source, Action`1 onNext, Action`1 onError, Action onCompleted)
at Microsoft.Phone.Reactive.ObservableExtensions.Subscribe[TSource](IObservable`1 source, Action`1 onNext)

This exception popped-up out of nowhere, without anything from the caller that would make that "Trampoline" method fail. No actual parameter passed to the Subscribe method was null, I made sure of that by using a precondition for calling Subscribe.

 

Well, it turns out that it's actually a bug that is related to the use of the infamous not-supported-but-silent ThreadStaticAttribute, for which I've had to work around to make umbrella work properly on Windows Phone 7.

The lack of a Thread Local Storage creates a concurrency issue around a priority queue that is kept by the CurrentThreadScheduler to perform delayed operations. The system wide queue was accessed by multiple threads at the same time, creating random NullReferenceExceptions.

This means that any call to the Subscribe method may have failed if an other call to that same method was being made at the same time.

 

In short, do not use the bundled version of Rx in Windows Phone 7 (as of NoDo), but prefer using the latest release from the DevLabs, which does not have this nasty bug.

[Reactive] Being fluent with CompositeDisposable and DisposeWith

By jay at April 04, 2011 13:48 Tags: , , ,

When you're writing a few queries with the reactive extensions, you'll probably end up doing a lot of this kind of code :

moveSubscription = Observable.FromEvent<MouseEventArgs>(this, "MouseMove")
                             .Subscribe(_ => { });

clickSubscription = Observable.FromEvent<MouseEventArgs>(this, "MouseClick")
                              .Subscribe(_ => { }); 

You'll probably call the dispose method on both subscriptions in some dispose method in the class that creates the subscriptions. But this is a bit too manual for my taste.

Rx provides the CompositeDisposable class, which is basically a list of IDisposable instances that all get disposed when CompositeDisposable.Dispose() is called. So we can write it like this :

var cd = new CompositeDisposable();

var moveSubscription = Observable.FromEvent<MouseEventArgs>(this, "MouseMove")
                                 .Subscribe(_ => { });
cd.Add(moveSubscription);

var clickSubscription = Observable.FromEvent<MouseEventArgs>(this, "MouseClick")
                                  .Subscribe(_ => { });
cd.Add(clickSubscription);

That's better in a sense that it is not needed to get my subscriprions out, but this is still too "manual". There are two lines for each subscriptions, and the need for temporary variables.

That's where a simple DisposeWith extension comes in handy :

public static class DisposableExtensions
{
 public static void DisposeWith(this IDisposable observable, CompositeDisposable disposables)
 {
     disposables.Add(observable);
 }
}

Very simple extension, a bit more fluent, and that allows to avoid creating a temporary variable just to unsubscribe on a subscription:

var cd = new CompositeDisposable();

Observable.FromEvent<MouseEventArgs>(this, "MouseMove")
          .Subscribe(_ => { })
          .DisposeWith(cd);

Observable.FromEvent<MouseEventArgs>(this, "MouseClick")
          .Subscribe(_ => { })
          .DisposeWith(cd);

This is a method with a side effect, but that's acceptable in this case, and it always ends the declaration of a observable query.

[WP7Dev] Double tap when you expect only one

By jay at March 27, 2011 19:24 Tags: , , ,

I've been developing a free application to do some PC remote control on Windows Phone 7, and it's been very instructive in many ways.

To improve the quality of the software, and be notified when an unhandled exception occurs somewhere in my code, or in someone else's code executed on my behalf, I've added a small opt-in unhandled exception reporting feature. This basically sends me back information about the device, most of what's available in DeviceExtendedProperties for device aggregation of exceptions, plus some informations like the culture and, of course, the exception stacktrace and details.

 

The MarketplaceDetailTask exception

A few recurring exceptions have popped up a lot recently, and one coming often is the following :

Exception : System.InvalidOperationException: Navigation is not allowed when the task is not in the foreground. Error: -2147220989 
at Microsoft.Phone.Shell.Interop.ShellPageManagerNativeMethods.CheckHResult(Int32 hr) 
at Microsoft.Phone.Shell.Interop.ShellPageManager.NavigateToExternalPage(String pageUri, Byte[] args) 
at Microsoft.Phone.Tasks.ChooserHelper.Navigate(Uri appUri, ParameterPropertyBag ppb) 
at Microsoft.Phone.Tasks.MarketplaceLauncher.Show(MarketplaceContent content, MarketplaceOperation operation, String context) 
at Microsoft.Phone.Tasks.MarketplaceDetailTask.Show() 

This code is called when a user clicks on the purchase image located on some page of the software, and it looks like this :


void PurchaseImage_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
{
    var details = new MarketplaceDetailTask();
    details.ContentIdentifier = "d0736804-b0f6-df11-9264-00237de2db9e";
    details.Show();
}

The call is performed directly on the image's ManipulationCompleted event.

I've been trying to reproduce it for a few times and I finally got it: The user is tapping more than once on the image.

I can see a few reasons why:

  • The ManipulationCompleted event is fairly sensitive and is raised multiple times when the user did not tap twice
  • The user did actually tap twice because the action did not answer fast enough.
  • The user tapped twice because he is used to always tap twice, as some PC users do... (You know, double clicking on hyperlinks in browsers, things like that)

 

What do we do about it ?

There may be actually more, be this actually tells me a lot.

First, I should be having some kind of visual feedback on the click of that image, to tell the user that he has done something (and also to actually follow the design guidelines)

Second, that even if the feedback is there, that there may always be two subsequent clicks, and one that may be executed after the first has called the MarketplaceDetailTask.Show(), and the application has been deactivated. I cannot do much about it, except handle the exception silently or track the actual application state and not call the method.

I'll go with the exception handler for now as it is not a very critical peace of code, but I'd rather have some way of that tell me that the application cannot do that reliably and not have to handle an exception. The API is rather limited on that side, where the PhoneApplicationService is only raising events and does not expose the current "activation" state.

 

Any other examples of exceptions ?

I'll talk more about some other findings this opt-in exception reporting feature has brought me, with some that seem to be pretty tricky. 

[WP7Dev][Reactive] Safer Reactive Extensions

By jay at September 06, 2010 20:26 Tags: , , , ,

Cet article est disponible en français.

When developing .NET applications, unhandled exception in threads have the undesirable effect of terminating the current process.

In the following example :

    static void Main(string[] args)
    {
        var t = new Thread(ThreadMethod);
        t.Start();

        Console.ReadLine();
    }

    private static void ThreadMethod()
    {
        Thread.Sleep(1000); throw new Exception();
    }

The basic exception will invariably terminate the process, and to prevent this, the exception needs to be handled properly :

    private static void ThreadMethod()
    {
        try
        {
            Thread.Sleep(1000); throw new Exception();
        }
        catch (Exception e)
        {
            // TODO: Log and report the exception
        }
    }

This makes classes like System.Threading.Thread, System.Threading.Timer or System.Threading.ThreadPool very dangerous to use if one wants to have an always running application. It is then required that no unhandled exception gets out of the custom handlers for these classes.

Even if it is possible to be notified when an exception has been raised and not handled properly, using the AppDomain.UnhandledException event, most the time this leads to the application being terminated. This termination behavior has been introduced in .NET 2.0, to prevent unhandled exception to be silently ignored.

While this is a very appropriate default behavior, in an enterprise environment, I’m usually enforcing custom static analysis or NDepend rules to prevent the use of these classes directly. This forces new code to use wrappers that provide a very wide exception handler and logs and reports the exception, but does not terminate the process. That also implies that there is still a very valid bug to be investigated, because exceptions should not be handled that late.

 

The case of the Reactive Framework

In Silverlight for Windows Phone 7, and in any other .NET 3.5 or .NET 4.0 application that uses the Reactive Extensions, it is very easy to switch between threads.

Reactive operators like Timer, BufferWithTime, ObserveOn or SubscribeOn allow for specific Schedulers like ThreadPool, TaskPool or NewThread to be used, and if a subscriber does not handle exceptions properly, it ends up with a terminated application.

The same exemple here also terminates the application :


    static void Main(string[] args)
    {
     Observable.Timer(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10))
                   .Subscribe(_=> ThreadMethod());

            Console.ReadLine();
    }

    private static void ThreadMethod()
    {
            throw new Exception();
    }

The Observable.Timer operator uses the System.Threading.Timer class and that makes it vulnerable to the same termination problems. Every subscriber needs to handle exceptions thrown in the OnNext delegate, or the application will terminate.

Also, do not think that the OnError delegate passed to Observable.Subscribe will handle exceptions thrown during the execution of OnNext code. OnError only notifies of errors generated by previous Reactive operators, not the current.

 

The IScheduler.AsSafe() extension method

Unfortunately, it is not possible for now to override the default schedulers used internally by the Reactive operators. The only way to handle all unhandled exceptions properly is to use the ObserveOn operator and intercept calls to IScheduler.Schedule methods. Calls can then be decorated with appropriate exception handlers to log and report the exception without terminating the process.

So, to be able to generalize this logging and reporting behavior, I created the AsSafe() extension that I place at the very top of a Reactive expression :

    Observable.Timer(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(10))
              .ObserveOn(Scheduler.ThreadPool.AsSafe())
              .Subscribe(_=> ThreadMethod());


And here is the code of this very simple extension method :


public static class SafeSchedulerExtensions
{
    public static IScheduler AsSafe(this IScheduler scheduler)
    {
        return new SafeScheduler(scheduler);
    }

    private class SafeScheduler : IScheduler
    {
        private IScheduler _source;

        public SafeScheduler(IScheduler scheduler) {
            this._source = scheduler;
        }

        public DateTimeOffset Now { get { return _source.Now; } }

        public IDisposable Schedule(Action action, TimeSpan dueTime)
        {
            return _source.Schedule(Wrap(action), dueTime);
        }

        public IDisposable Schedule(Action action)
        {
            return _source.Schedule(Wrap(action));
        }

        private Action Wrap(Action action)
        {
            return () => {
                try  {
                    action();
                }
                catch (Exception e) {
                    // Log and report the exception.
                }
            };

        }
    }
}

[WP7] Using an Exchange Account With a Custom Certificate

By jay at July 31, 2010 15:07 Tags: ,

Depending on which corporation you work for, you may have to connect to your exchange server using a self-signed server certificate to be used with HTTPS protocol (using either TLS or SSL).

If you're unlucky enough to be in this situation, but are using a modern browser, you can install the certificate in either your windows certificate store, or using your browser's store. You can do that using this lengthy technique for IE8.

But if you're on a Windows Phone 7, if you try to connect to your exchange account, you'll get a nice message telling you that there is a problem with the server certificate. Well, neither Internet Explorer or the bundled Exchange tools give you the ability to install that custom certificate. And there is no access to the file system either.

Luckily, you can email your certificate on your GMail account for instance, and the WP7 mail client has the ability to install certificates !

So, use the lengty technique to export your certificate in the ".cer" format by connecting to your exchange server using its HTTPS address in Internet Explorer on your PC, email it to yourself, and tap on it on your Windows Phone 7 to install it.

Now you can enjoy having your work emails and calendars on your weekends, in case you don't have anything else better to do :)

 

EDIT: If it still does not work, you may need to also import the full chain of certificates, up to the root. To do so, in the certificate from your exchange server, open the "Certification Path" tab, then for each item in the tree, click "View Certificate", then "Details", then "Copy to File...". Email each certificate to your Windows Phone and you're done !

Revisited with the Reactive Extensions: DataBinding and Updates from multiple Threads

By Admin at July 26, 2010 18:42 Tags: , , ,

Cet article est disponible en francais.

Recently, I wrote an article about WinForms, DataBinding and Updates from multiple threads, where I showed how to externalize the execution of event handler code on the UI thread.

I used a technique based on Action<Action> that takes advantage of closures, and the fact that an action will carry its context down to the point where it is executed. All this with no strings attached.

This concept of externalization can be revisited with the Reactive Extensions, and the IScheduler interface.

 

The Original Sample

But let's get right to the original code sample :

    public MyController(Action<Action> synchronousInvoker)
    {
        _synchronousInvoker = synchronousInvoker;
        ...
    }

This code is the constructor of the controller for my form, and the synchronous invoker action will take something like this :

    _controller = new MyController(a => Invoke(a));

And the invoker lambda is used like this :


    _synchronousInvoker(
        () => PropertyChanged(this, new PropertyChangedEventArgs("Status"))
    );

Where Invoke is actually Control.Invoke(), used to execute code on the UI Thread where updates to the UI controls can be safely executed.

While the Action<Action> trick is working just fine in acheiving the isolation of concerns, it is not very obvious just by looking at the constructor signature what you are supposed to pass to it.

 

Using the IScheduler interface

To be able to abstract the location used to execute the content of Reactive operators, the Rx team introduced the concept of Scheduler, with a bunch of default scheduler implementations.

It basically exposes an abstracted way for users of the IScheduler instance to schedule the execution of a method in the specific way defined by the scheduler. In our case, we want to execute our handler code on the WinForms message pump, and "there's a scheduler for that".

The sample can be easily updated to use the IScheduler instead of the Action<Action> delegate, and make use of the IScheduler.Schedule() method.

    public MyController(ISheduler scheduler)
    {
        _scheduler = scheduler;
        ...
    }

And replace the call by :


    _scheduler.Schedule(
        () => PropertyChanged(this, new PropertyChangedEventArgs("Status"))
    );

Not a very complex modification, but it is far more readable.

And we can use the provided scheduler for the Winforms, the yet undocumented System.Concurrency.ControlScheduler which is not in the Scheduler class because it cannot be created statically and requires a Control instance :

    _controller = new MyController(new ControlScheduler(this));

where this is an instance of a control.

This is much better, and for the unit testing of the Controller, you can easily use the System.Concurrency.CurrentThreadScheduler, because you don't need to switch threads in this context.

 

What about the Reactive Extensions and Silverlight for Windows Phone 7 ?

In a very strange move, the WP7 team moved the IScheduler class from System.Concurrency to the very specific Microsoft.Phone.Reactive namespace.

I do not quite understand the change of namespace, and it makes code that used to compile easily on both platforms not compatible.

Maybe they considered the Reactive Extensions implementation for Windows Phone too different from the desktop implementation... But the compact framework was built around that assertion, and most of the common code stays in the same namespaces.

If someone has an explanation for that strange refactoring, I'm listening :)

[WP7Dev] Using the WebClient with Reactive Extensions for Effective Asynchronous Downloads

By jay at June 22, 2010 21:07 Tags: , , , , ,

There’s a very cool framework that has slipped into the Windows Phone SDK : The Reactive Extensions.

It's actually a quite misunderstood framework, mainly because it is a bit hard to harness, but when you get a handle on it, it is very handy ! I particularly like the MemoizeAll extension, a tricky one, but very powerfull.

But I digress.

 

A Non-Reactive String Download Sample

On Windows Phone 7, the WebClient class only has a DownloadStringAsync method and a corresponding DownloadStringCompleted event. That means that you're forced to be asynchronous, to be nice to the UI and not make the application freeze on the user, because of the bad coding habit of being synchronous on remote calls.

In a world without the reactive extensions, you would use it like this :

public void StartDownload()
{
    var wc = new WebClient();
    wc.DownloadStringCompleted += 
      (e, args) => DownloadCompleted(args.Result);
                  
    // Start the download
    wc.DownloadStringAsync(new Uri("http://www.data.com/service"));
}

public void DownloadCompleted(string value)
{
    myLabel.Text = value;
}

Pretty easy. But you soon find out that the execution of the DownloadStringCompleted event is performed on the UI Thread. That means that if, for some reason you need to perform some expensive calculation after you’ve received the string, you’ll freeze the UI for the duration of your calculation, and since the Windows Phone 7 is all about fluidity and you don't want to be the bad guy, you then have to queue it in the ThreadPool.

But you also have to update the UI in the dispatcher, so you have to come back from the thread pool.

You then have :

 public void StartDownload()
 {
     WebClient wc = new WebClient();
     wc.DownloadStringCompleted += 
        (e, args) => ThreadPool.QueueUserWorkItem(d => DownloadCompleted(args.Result));

     // Start the download
     wc.DownloadStringAsync(new Uri("http://www.data.com/service"));
  }

 public void DownloadCompleted(string value)
 {
     // Some expensive calculation
     Thread.Sleep(1000);

     Dispatcher.BeginInvoke(() => myLabel.Text = value);
 }

That’s a bit more complex. And then you notice that you also have to handle exceptions because, well, it’s the Web. It’s unreliable.

So, let’s add the exception handling :

public void StartDownload()
{
    WebClient wc = new WebClient();

    wc.DownloadStringCompleted += (e, args) => {
        try {
            ThreadPool.QueueUserWorkItem(d => DownloadCompleted(args.Result));
        }
        catch (WebException e) {
            myLabel.Text = "Error !";
        }
    };
   
    // Start the download
    wc.DownloadStringAsync(new Uri("http://www.data.com/service"));
}

public void DownloadCompleted(string  value)
{
    // Some expensive calculation
    Thread.Sleep(1000);
    Dispatcher.BeginInvoke(() => myLabel.Text = value);
}

That’s starting to be a bit complex. But then you have to wait for an other call from an other WebClient to end its call and show both results.

Oh well. Fine, I'll spare you that one.

 

The Same Using the Reactive Extensions

The reactive extensions treats asynchronous events like a stream of events. You subscribe to the stream of events and leave, and you let the reactive framework do the heavy lifting for you.

I’ll spare you the explanation of the duality between IObservable and IEnumerable, because Erik Meijer explains it very well.

So, I’ll start again with the simple example, and after adding the System.Observable and System.Reactive references, I can downloading a string :

public void StartDownload()
{
    WebClient wc = new WebClient();

    var o = Observable.FromEvent<DownloadStringCompletedEventArgs>(wc, "DownloadStringCompleted")

                      // When the event fires, just select the string and make
                      // an IObservable<string> instead
                      .Select(newString => newString.EventArgs.Result);

    // Subscribe to the observable, and set the label text
    o.Subscribe(s => myLabel.Text = s);


    // Start the download
    wc.DownloadStringAsync(new Uri("http://www.data.com/service"));
}

This does the same thing the very first example did. You’ll notice the use of Observable.FromEvent to transform the event into a string from the DownloadStringCompleted event args. For this exemple, the event stream will only contain one event, since the download only occurs once. Each of these ocurrence of the event is then “projected”, using the Select statement, to a string that represents the result of the web request.

It’s a bit more complex for the simple case, because of the additional plumbing.

But now we want to handle the threads context changes. The Reactive Extensions has the concept of scheduler, to observe an IObservable in a specific context.

So, we use the scheduler like this :

public void StartDownload()
{
    WebClient wc = new WebClient();

    var o = Observable.FromEvent<DownloadStringCompletedEventArgs>(wc, "DownloadStringCompleted")

                      // Let's make sure that we’re on the thread pool
                      .ObserveOn(Scheduler.ThreadPool)

                      // When the event fires, just select the string and make
                      // an IObservable<string> instead
                      .Select(newString => ProcessString(newString.EventArgs.Result))

                      // Now go back to the UI Thread
                      .ObserveOn(Scheduler.Dispatcher)

                      // Subscribe to the observable, and set the label text
                      .Subscribe(s => myLabel.Text = s);

    wc.DownloadStringAsync(new Uri("http://www.data.com/service"));
}

public string ProcessString(string s)
{
    // A very very very long computation
    return s + "1";
}
 

In this example, we’ve changed contexts twice to suit our needs, and now, it’s getting a bit less complex than the original sample.

And if we want to handle exceptions, well, easy :

    .Subscribe(s => myLabel.Text = s, e => myLabel.Text = "Error ! " + e.Message);

And you have it !

 

Combining the Results of Two Downloads

Combining two or more asynchronous operations can be very tricky, and you have to handle exceptions, rendez-vous and complex states. That make a very complex piece of code that I won’t write here, I promised, but instead I’ll give you a sample using Reactive Extensions :

public IObservable<string> StartDownload(string uri)
{
    WebClient wc = new WebClient();

    var o = Observable.FromEvent<DownloadStringCompletedEventArgs>(wc, "DownloadStringCompleted")

                      // Let's make sure that we're not on the UI Thread
                      .ObserveOn(Scheduler.ThreadPool)

                      // When the event fires, just select the string and make
                      // an IObservable<string> instead
                      .Select(newString => ProcessString(newString.EventArgs.Result));

    wc.DownloadStringAsync(new Uri(uri));

    return o;
}

public string ProcessString(string s)
{
    // A very very very long computation
    return s + "<!-- Processing End -->";
}

public void DisplayMyString()
{
    var asyncDownload = StartDownload("http://bing.com");
    var asyncDownload2 = StartDownload("http://google.com");

    // Take both results and combine them when they'll be available
    var zipped = asyncDownload.Zip(asyncDownload2, (left, right) => left + " - " + right);

    // Now go back to the UI Thread
    zipped.ObserveOn(Scheduler.Dispatcher)

          // Subscribe to the observable, and set the label text
          .Subscribe(s => myLabel.Text = s);
}

You’ll get a very interesting combination of google and bing :)

[WP7Dev] Beware of the [ThreadStatic] attribute on Silverlight for Windows Phone 7

By Admin at June 19, 2010 21:36 Tags: , , , , , , ,

Cet article est disponible en francais.

In other words, it is not supported !

And the worst in all this is that you don’t even get warned that it’s not supported... The code compiles, but the attribute has no effect at all ! Granted that you can read the msdn article about the differences between silverlight on Windows and Windows Phone, but well, you may still miss it. Maybe a custom code analysis rule could prevent this.

Still, you want to use ThreadStatic because you probably need it, somehow. But since it is not supported, you could try the Thread.GetNamedDataSlot, mind you.

Well, too bad. It’s not supported either.

That leaves us implementing or own TLS implementation, by hand...

 

Updating Umbrella for Silverlight on Windows Phone

I’m a big fan of Umbrella, and the first time I had to use Dictionary<>.TryGetValue and its magically aweful out parameter in my attempt to rewrite my Remote Control app for Windows Phone 7, I decided to port Umbrella to it. So I could use GetValueOrDefault without rewriting it, again.

I managed to get almost all the desktop unit tests to pass, except for those who emit code, use web features, use xml and binary serializers, call private methods using reflection, and so on.

There are a few parts where the code needed to be updated, because TypeDescriptor class is not available on WP7, you have to crash and burn to see if a value is convertible from one type to the other. But that’s not too bad, it works as expected.

 

Umbrella’s ThreadLocalSource

Umbrella has this nice ThreadLocalSource class that wraps the TLS behavior, and you can easily create a static variable of that type instead of the ThreadStatic static variable.

The Umbrella quick start samples make that kind of use for it :

    ISource<int> threadLocal = new ThreadLocalSource<int>(1);

    int valueOnOtherThread = 0;

    Thread thread = new Thread(() => valueOnOtherThread = threadLocal.Value);
    thread.Start();
    thread.Join();

    Assert.Equal(1, threadLocal.Value);
    Assert.Equal(0, valueOnOtherThread);

The main thread set the value to 1, and the other thread tries to get the same value from the other thread and it should be different (the default value of an int, which is 0).

 

Updating the ThreadLocalSource to avoid the use of ThreadStatic

The TLS in .NET is basically a dictionary of string/object pairs that is attached to each running threads. So, to mimic this, we just need to make a list of all threads that want to store something for themselves and wrap it nicely.

We can create a variable of this type :

    private static Tuple<WeakReference, IDictionary<string, T>>[] _tls;

That variable is intentionally an array to try to make use of memory spacial locality, and since on that platform we won’t get a lot of threads, this should be fine when we got through the array to find one. This approach is trying to be lockless, by using a retry mechanism to update the array. The WeakReference is used to avoid keeping a reference to the thread after it has been terminated.

So, to update the array, we can do as follows :

    private static IDictionary<string, T> GetValuesForThread(Thread thread)
    {
        // Find the TLS for the specified thread
        var query = from entry in _tls

                    // Only get threads that are still alive
                    let t = entry.T.Target as Thread

                    // Get the requested thread
                    where t != null && t == thread
                    select entry.U;

        var localStorage = query.FirstOrDefault();

        if (localStorage == null)
        {
            bool success = false;

            // The storage for the new Thread
            localStorage = new Dictionary<string, T>();

            while(!success)
            {
                // store the original array so we can check later if there has not
                // been anyone that has updated the array at the same time we did
                var originalTls = _tls;

                var newTls = new List<Tuple<WeakReference, IDictionary<string, T>>>();

                // Add the slots for which threads references are still alive
                newTls.AddRange(_tls.Where(t => t.T.IsAlive));

                var newSlot = new Tuple<WeakReference, IDictionary<string, T>>()
                {
                    T = new WeakReference(thread),
                    U = localStorage
                };

                newTls.Add(newSlot);

                // If no other thread has changed the array, replace it.
                success = Interlocked.CompareExchange(ref _tls, newTls.ToArray(), originalTls) != _tls;
            }
        }

        return localStorage;
    }

Instead of the array, another dictionary could be created but I’m not sure of the actual performance improvement that would provide, particularly for very small arrays.

Using a lockless approach like this one will most likely limit the contention around the use of that TLS-like class. There may be, from time to time, computations that are performed multiple times in case of race conditions on the update of the _tls array, but that is completely acceptable. Additionally, livelocks are also out of the picture on that kind of preemptive systems.

I think developing on that platform is going to be fully of little workarounds like this one... This is going to be fun !

About me

My name is Jerome Laban, I am a Software Architect, C# MVP and .NET enthustiast from Montréal, QC. You will find my blog on this site, where I'm adding my thoughts on current events, or the things I'm working on, such as the Remote Control for Windows Phone.