4

I have to deal with a strange problem, at least from my point of view. I use a Task to wait untill a variable gets a specific value and then run the Continue part on the ui thread again.

Problem now is that before I call StartNew() and inside the call the ManagedThreadId is the same and it freezes my UI.

Here my code:

// ManagedThreadId here
Task.Factory.StartNew(() => 
{
    // and here are the same.
    while (isClosing)
    {
        Thread.Sleep(50);
    }
}).ContinueWith((finishedTask) => 
{
    if (currentContainer != null)
    {
        window = currentContainer;
    }
    else
    {
         window = CreateBallonWindow();
         window.Show();
    }

    window.Activate();
}, TaskScheduler.FromCurrentSynchronizationContext());

Ideas?

Thanks Christoph

EDIT:

Most interesting for me is why this happens not how to get around this issue. I want to understand what happens there...

christoph
  • 1,019
  • 1
  • 12
  • 23
  • Yeah, but I don´t want to raise an action everytime that window is closed. I just want to make sure it is closed that time I open a new one. Besides, more interesting on how to get around this issue for me it is to understand why both is executed on the same thread. Sorry if that didn´t come out of my question. – christoph Jul 17 '13 at 14:31
  • I have thrown together a sample app and it works fine for me, however, when you queried the managed ID, did you put it into a variable that had a closure wrapped around it? My UI thread ID comes out as 9, my inner thread ID (from `ThreadPool`) comes out as 10. – Adam Houldsworth Jul 17 '13 at 14:32
  • 3
    `Task.Factory.StartNew` is not guaranteed to spawn a new thread check [This answer](http://stackoverflow.com/a/7889800/1834662) for some details and the first 2 comments on it too. You could also try specifying `TaskCreationOptions.LongRunning` as the 4th comment on that linked answer mentions to force spawn a new thread for the Task – Viv Jul 17 '13 at 14:33
  • @Viv Does it not use the default `TaskScheduler` if one is not provided? For me this is the `ThreadPool` (according to my debugger). – Adam Houldsworth Jul 17 '13 at 14:36
  • Check what `TaskScheduler.FromCurrentSynchronizationContext()` returns at runtime. If you already *are* on the threadpool the threadid might stay the same. – usr Jul 17 '13 at 14:39
  • I´m afraid I don´t get the point. What does ThreadPool have to deal with it and how can I check whether I´m on or not? Besides I noticed that this behaviour only appears if I have used TaskScheduler.FromCurrentSynchronizationContext() previously, it is maybe of some help – christoph Jul 17 '13 at 14:45
  • @christoph I did exactly your code, except I was just setting a label text in a WinForms app, perhaps this is a different between WinForms and WPF as to why mine works without issue. But I think the way you are reviewing the Managed Id might be the cause of the problem (and a red herring), can you post the code for how you do that? – Adam Houldsworth Jul 17 '13 at 14:47
  • @AdamHouldsworth I think your question might be close to [this question](http://stackoverflow.com/q/6800705/1834662) – Viv Jul 17 '13 at 14:48
  • @christoph was that comment addressed at mine? What does TaskScheduler.FromCurrentSynchronizationContext().GetType() print? Print the value right before you invoke StartNew. – usr Jul 17 '13 at 14:48
  • @Viv Thanks for that, tagged it for Instapaper read later :-) – Adam Houldsworth Jul 17 '13 at 14:48
  • @AdamHouldsworth: I work at some sample code to reproduce this issue out of the box. I will post it as soon as it works (or better not works) – christoph Jul 17 '13 at 14:58
  • @usr: Yes it was addressed to you, sorry. GetType() returned "System.Threading.Tasks.SynchronizationContextTaskScheduler" – christoph Jul 17 '13 at 14:59
  • @christoph one final check: What does `SynchronizationContext.Current.GetType()` evaluate to? – usr Jul 17 '13 at 15:08
  • @usr result was "System.Windows.Threading.DispatcherSynchronizationContext" – christoph Jul 17 '13 at 15:41

1 Answers1

3

Thank you all for your hints,

I finally think that I got it. The problem here is that TaskScheduler.Current is the default scheduler used when calling StartNew() . And this is no good combination when using TaskScheduler.SynchronizationContext().

The case here was that I (indirectly) used StartNew() in the continuing task with the scheduler described by TaskScheduler.SynchronizationContext(). So that the default scheduler was the one which contains the ui thread --> the new Task got invoked on the ui thread.

Special thanks to Viv, for sharing the link. It helped a lot to understand what was going on.

Christoph

christoph
  • 1,019
  • 1
  • 12
  • 23
  • That was my suspicion :) Somehow calling StartNew with the wrong scheduler or sync context. – usr Jul 17 '13 at 16:59
  • @usr yep, but if you have answered this right after I posted the question I suppose I would not have understood without all the comments :) – christoph Jul 18 '13 at 06:25