【问题标题】:The calling thread cannot access this object error调用线程无法访问此对象错误
【发布时间】:2013-07-02 10:14:56
【问题描述】:

我正在尝试在后台线程中创建动态自定义 userControl。 这是我创建新线程的方法:

var thread = new Thread(CreateItemInBackgroundThread);
thread.SetApartmentState(ApartmentState.STA);            
thread.Start();
thread.Join();

这是方法CreateItemInBackgroundThread

var uc = new MyUserControl();
UserControl item = uc;
AllControls.Add(item);
//Here I am trying to add control to a current Tab
foreach (var currentTab in _allTabs)
{
    currentTab.DocumentWindow.Dispatcher.BeginInvoke(new Action(() =>
                                                            {
                                                                if (tab.DocumentWindow.IsSelected)
                                                                {
                                                                    tempTab = tab;
                                                                    tempControl = item;
                                                                    finish = true;
                                                                }

                                                            }));
}

这是我的完成属性

bool finish
    {
        get { return _finish; }
        set
        {
            _finish = value;
            if (_finish)
            {
                tempTab.AnimatedCanvas.Dispatcher.BeginInvoke(new Action(() => tempTab.AnimatedCanvas.Children.Add(tempControl)));
            }
        } // Here I get error - The calling thread cannot access this object because a different thread owns it
    }

我怎样才能避免这个错误以及为什么会发生这个错误?

【问题讨论】:

  • 另外你为什么要尝试使用某些特定对象的调度程序?只需使用Application.Current.Dispatcher
  • 我想访问 tempControl,我的动态创建的元素被保存并放到 UI 中,但是在我的属性中我总是出现这个错误

标签: c# wpf multithreading


【解决方案1】:

正如错误所说,您无法访问 this 对象,因为另一个线程拥有它,因此您可以使用 Invoke(Delegate Method) 调用该线程 您可以使用tempTab.InvokeRequired检查是否需要调用

【讨论】:

    【解决方案2】:

    出现此错误是因为您必须在同一个线程上执行不同的任务,例如 U 无法使线程异步并使用同一线程更新 UI。这将导致冲突。因为 UI 线程是主线程。

    您可以使用 BAckground Worker Thread 并将其两个 eventHandlers 订阅到您想要处理的事件中......例如-

    BackgroundWorker Worker=new BackgroundWorker();
    worker.DoWork+=Yorevent which will do the timeTaking Task();
    Worker.RunWorkerCompleted+=YOurEvent which will Update your UI after the work is done();
    worker.RunWorkerAsync();
    

    RunWorkerAsync() 将使您的线程异步并在后台工作 这样它也不会导致任何线程错误..

    【讨论】:

    • 好主意,但是 backgroundWorker 在这里没有用,因为我需要使用 ApartmentState.STA 创建自定义用户控件
    猜你喜欢
    • 2012-03-22
    • 2013-07-31
    • 1970-01-01
    • 1970-01-01
    • 2021-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多