线程和任务对我来说是一个很大的谜。
必须在与DependencyObject相同的线程上创建DependencySource。
我试图避免一个冻结的UI。我的方法是在线程中工作,然后在线程输出后设置属性。
我有一个作业的基类。基本上,它是一个包装器,用Input和Output变量启动一个新线程。我启动一个新线程,等待直到工作完成,并尝试将其设置为我的属性MyFoo。但这行不通。参见上面引用的错误信息。
我如何使用线程*而不阻塞UI并将结果设置为WPF中的属性?
我不关心它是一个线程,一个任务或任何东西,只要它不阻塞我的UI。
// ...
FooJob job = new FooJob {Input = input};
job.Start();
while (!job.IsDone) Wait(0.05);
MyFoo = (BitmapSource) job.Output;
我所尝试的是将输出设置为我的字段而不是我的属性,并手动调用OnPropertyChanged。
这里实际的包装器类
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;
}
}
得到异常的原因必须在与DependencyObject相同的线程上创建DependencySource。表示BitmapSource
已在新线程上创建,除非在UI线程上创建,否则无法将BitmapSource
绑定到UI。然而,因为BitmapSource
是可冻结的,你也可以"冻结"它,以消除它的线程亲和力。因此,如果你真的需要在另一个线程上创建BitmapSource
,你必须在BitmapSource
上调用Freeze
,然后才能将其绑定到UI。