调用线程无法访问此对象,因为另一个线程拥有它

时间:2011-08-16 09:40:47

标签: c# wpf

我知道网站上已经多次询问过这个问题,但是我已经尝试按照给出的建议,但我无处可去。

我有一个从单独的线程调用的方法,它只是将一个TextBlock添加到GUI上的stackpanel。但无论我如何尝试实现这一点,我都会收到错误:“调用线程无法访问此对象,因为另一个线程拥有它”

道歉,如果这是一个非常简单的问题,但我对WPF来说是全新的......

private void AddTbToStackPanel(string text)
    {
        StackPanel stackPanel = stackPanel1 as StackPanel;
        TextBlock tb = new TextBlock();
        tb.Text = text;            
        stackPanel.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => { stackPanel.Children.Add(tb); }));
    }

4 个答案:

答案 0 :(得分:4)

您正在工作线程中创建文本块。

new TextBlock()移动到lambda。

stackPanel.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
     () => { stackPanel.Children.Add(new TextBlock { Text = text }); }));

答案 1 :(得分:3)

刚想通了 - 我需要在所有对象上使用Dispatcher,如下所示:

private void AddTbToStackPanel(string text)
    {
        Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() =>
        {
            StackPanel stackPanel = stackPanel1 as StackPanel;
            TextBlock tb = new TextBlock();
            tb.Text = text;                
            stackPanel.Children.Add(tb);
        }));
    }

答案 2 :(得分:1)

    private void AddTbToStackPanel(string text)
    {
        this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)(() => {
            StackPanel stackPanel = stackPanel1 as StackPanel;
            TextBlock tb = new TextBlock();
            tb.Text = text;
            stackPanel.Children.Add(tb);
        }));
    }

答案 3 :(得分:0)

以下示例可帮助您实现任务和UI更新。您可以轻松地将以下示例转换为您的方案。 您可以查看我的博客,其中包含有关此错误和解决方案的详细说明

http://bathinenivenkatesh.blogspot.com/2011/07/wpf-build-more-responsive-ui.html

ObservableCollection images = new ObservableCollection(); 
TaskFactory tFactory = new TaskFactory(); 
tFactory.StartNew(() => 
{ 
for (int i = 0; i < 50; i++) 
{ 
//GET IMAGE Path FROM SERVER 
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate() 
{ 
// UPDATE PROGRESS BAR IN UI 
}); 

images.Add((""); 
} 

}).ContinueWith(t => 
{ 
if (t.IsFaulted) 
{ 
// EXCEPTION IF THREAD IS FAULT 
throw t.Exception; 
} 
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate() 
{ 
//PROCESS IMAGES AND DISPLAY 
}); 
});