2

Threads and Tasks are unfortunately a big mystery for me.

Must create DependencySource on same Thread as the DependencyObject.

I am trying to avoid a freezing UI. My approach was doing work in a thread and setting properties later with output from the thread.
I've a base class for a Job. Basically it's a wrapper that starts a new thread with an Input and Output variable. I start a new thread, wait until the job is done and try to set it to my property MyFoo. But this won't work. See above quoted error message.


How can I use a thread* without blocking the UI and set the result to an property in WPF?
* I actually don't care if it is a thread, a task or whatever as long as it is not blocking my UI.

        // ...
        FooJob job = new FooJob {Input = input};
        job.Start();
        while (!job.IsDone) Wait(0.05);
        MyFoo = (BitmapSource) job.Output;


What I've tried is to set the output to my field instead of my Property and call OnPropertyChanged manually.


Here the actual wrapper class

public class Job {
    public object Output;
    public object Input;

    private bool _isDone;
    private readonly object _handle = new object();
    private Thread _thread;

    public bool IsDone {
        get {
            bool tmp;
            lock (_handle) {
                tmp = _isDone;
            }
            return tmp;
        }
        set {
            lock (_handle) {
                _isDone = value;
            }
        }
    }

    public virtual void Start() {
        _thread = new Thread(Run);
        _thread.Start();
    }

    protected virtual void ThreadFunction() {}

    private void Run() {
        ThreadFunction();
        IsDone = true;
    }
}
boop
  • 7,413
  • 13
  • 50
  • 94
  • Closed. See my answer in the duplicated question for a basic introduction on how to work with WPF UIs in a multi-threaded scenario. After reading that, if you have a specific question regarding a specific piece of WPF-related code, post a new question including that code and the relevant XAML. – Federico Berasategui Aug 17 '14 at 00:34
  • Well, this throws the exact same error. – boop Aug 17 '14 at 00:41
  • @HighCore: While your answer is a good description of the "WPF mentality" it does not address the specific problem in this question where a `BitmapSource` is created on another thread. The `BitmapSource` can be frozen which removes it's thread affinity. – Martin Liversage Aug 17 '14 at 00:41

1 Answers1

3

The reason you get the exception Must create DependencySource on same Thread as the DependencyObject. is an indication that the BitmapSource has been created on a new thread and you will not be able to bind the BitmapSource to the UI unless you create it on the UI thread. However, because BitmapSource is freezable you can also "freeze" it to remove it's thread affinity. So if you really need to create a BitmapSource on another thread you will have to call Freeze on the BitmapSource before you can bind it the UI.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256