使用由其他线程创建的对象

时间:2012-04-20 16:45:02

标签: c# wpf multithreading share dependencyobject

我只是想在另一个线程中更改窗口的背景。有两个程序,一个是工作正常,另一个是抛出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程序中,线程是否只能使用由自己的线程创建的对象? 谢谢你的回复。

3 个答案:

答案 0 :(得分:1)

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

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

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

如果args是params对象数组,那么你可以放置params。

现在,如果你正在使用一些Freezable对象(例如一些Image,Brush,Transform或Geometry),那么在将它发送到UI线程之前你需要object.Freeze();

答案 1 :(得分:0)

是的,正确,这不仅仅是关于WPF,而是关于Windows programming

您无法从与其自身不同的其他线程更新UI对象。

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

答案 2 :(得分:0)

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