1

我只想在另一个线程中更改窗口的背景。有两个程序,一个是正常工作,另一个抛出 InvalidOperationException。

正确的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Thread t = new Thread(new ParameterizedThreadStart(threadTest));
        t.Start(@"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg");
    }

    void threadTest(object obj)
    {
        string path = obj as string;
        this.Dispatcher.Invoke(new Func<object>(() => this.Background = new 
    }
}

错误代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        Thread t = new Thread(new ParameterizedThreadStart(threadTest));
        t.Start(@"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg");
    }

    void threadTest(object obj)
    {
        string path = obj as string;
        //this.Dispatcher.Invoke(new Func<object>(() => this.Background = new ImageBrush(new BitmapImage(new Uri(path)))));
        ImageBrush background = new ImageBrush(new BitmapImage(new Uri(path)));
        this.Dispatcher.Invoke(new Func<object>(() => this.Background = background));
    }
}

这些代码的不同之处在于,错误代码在子线程中创建了 ImageBrush 对象。所以我的问题是:在wpf程序中,线程是否只能使用自己线程创建的对象?感谢您的回复。

4

3 回答 3

1

是的你是对的。只有 UI 线程可以使用它创建的对象。因此,您可以使用 Dispatcher 将 UI 操作“排队”到它的正确线程上。

回答你的第二个问题,当然,有一种方法可以将对象“传递”到 UI 线程。如果您看到 BeginInvoke 结构(Dispatcher 的),它是:

public DispatcherOperation BeginInvoke(
    Delegate d,
    params Object[] args
)

args 是 params 对象数组,那里是你放置 params 的地方。

现在,如果您正在使用某些Freezable对象(例如某些图像、画笔、变换或几何图形),那么您需要object.Freeze();在将其发送到 UI 线程之前。

于 2012-04-20T16:47:26.060 回答
0

是的,正确的,它不仅是关于WPF,而且在一般情况下,关于Windows programming

您不能从不同于它自己的其他线程更新 UI 对象。

这样做的原因很简单,因为必须保证消息泵送,尤其是传递到 OS 的目标控制。这对于使用 的通信自然有效SendMesage,但PostMessage也适用。

于 2012-04-20T16:59:40.467 回答
0

如果您在单独的线程上创建一个对象,如果您先冻结它,您可能会在 gui 线程上使用它。请参阅可冻结对象

于 2012-04-20T17:27:52.530 回答