2

Is it safe to store the TaskScheduler of the UI Thread in a field as following:

class TaskSchedulerReference {

    private readonly _uiTaskScheduler; 

    // Constructor is called by the UI Thead 
    public TaskSchedulerReference() {
        _uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext()
    }

    public TaskScheduler UiTaskScheduler { get { return _uiTaskScheduler; } }
}

...so that it is possible to notify the UI at any time from any background thread in a Task.ContinueWith(action, TaskSchedulerReference.UiTaskScheduler)callback.

Is it guaranteed that the reference remains valid during the whole application life-cycle?

jeromerg
  • 2,997
  • 2
  • 26
  • 36
  • 2
    This static initializer is very dangerous. Please refer to [my answer](http://stackoverflow.com/questions/25751465/prism-5-delegatecommandbase-raisecanexecutechanged-throws-invalidoperationexcept/27406194#27406194) where I explain how can such a thing mess up the whole app. It's not guaranteed that this field will be initialized on the UI thread. – dymanoid Feb 24 '15 at 16:23
  • Note that this isn't the SC, it's a `TaskScheduler` that uses the SC. – i3arnon Feb 24 '15 at 16:59
  • Plese forget the static initializer. It is not the point. I correct the question... – jeromerg Feb 24 '15 at 17:07
  • @dymanoid not really dangerous :) - somewhat random, can be called at any particular time from any context, will kill class on failure - but otherwse perfectly safd. – Alexei Levenkov Feb 24 '15 at 20:25

2 Answers2

5

Apart from that dubious // This class is first visited by the UI Thread, yes. Use an explicit initializer (explicitly run from the UI thread) instead, the JIT is not guaranteed to run the class initializer on the UI thread.

However, I prefer capturing the context as a local variable. Exposing anything as global state is tricky in multi-threading (and asynchronous programming). Always try using as local a state as possible. It also reeks of the old IsInvokeRequired pattern. Every method should be very explicit about what happens where - it's very easily to accidentally introduce re-entrant code and deadlocks otherwise.

Luaan
  • 62,244
  • 7
  • 97
  • 116
  • Thank you. My fear doesn't relate to the static field (the example was just to provide an illustration): The question is rather : may a reference to the SynchronizationContext become invalid? In particular, I fear calls to `SynchronizationContext.SetSynchronizationContext(context)`, that would make the stored field completely out-of-date... – jeromerg Feb 24 '15 at 17:05
  • 1
    @jeromerg Yeah, you don't have to fear that in a windows forms application - if you have more than a single synchronization context, you're in trouble anyway :D . If you ever find yourself writing a web application, though, it will not work - that's yet another reason to pass the context rather than having it in a global field somewhere. – Luaan Feb 25 '15 at 08:28
0

If you look at the code for FromCurrentSynchronizationContext you can see that it creates a SynchronizationContextTaskScheduler by capturing SynchronizationContext.Current.

As long as you do that on the UI thread you would capture the UI's SC and SynchronizationContext.SetSynchronizationContext(context) can't change your captured context.

Note that what you store is a TaskScheduler that holds the SC and not the SC itself. If you want to capture the SC just use SynchronizationContext.Current.

i3arnon
  • 113,022
  • 33
  • 324
  • 344