【问题标题】:"The calling thread cannot access this object because a different thread owns it"“调用线程无法访问此对象,因为不同的线程拥有它”
【发布时间】:2013-08-20 19:52:34
【问题描述】:

我有一个使用多线程来执行通知的 WPF 应用程序。但是我遇到了“调用线程无法访问此对象,因为不同的线程拥有它”的问题。例外。

当我的主窗口被加载时,我为通知窗口创建一个新线程

private void RibbonWindow_Loaded(object sender, RoutedEventArgs rae)
{
    Thread newWindowThread = new Thread(new ThreadStart(() =>
    {
        var reminders = new List<Reminder>();

        // Go to the database to get active reminders...

        var notificationsViewModel = new NotificationsViewModel(reminders);
        var notificationsView = new NotificationsView();
        notificationsView.DataContext = notificationsViewModel;
        var checkAccess = notificationsView.Dispatcher.CheckAccess();

        if (checkAccess)
        {
            notificationsView.Show();
        }

        System.Windows.Threading.Dispatcher.Run();
    }));

    newWindowThread.IsBackground = true;
    newWindowThread.SetApartmentState(ApartmentState.STA);
    newWindowThread.Start();
}

视图的构造函数是默认的:

public partial class NotificationsView : Window
{
    public NotificationsView()
    {
        InitializeComponent();
    }
}

要绑定的视图模型和模型的构造函数

public NotificationsViewModel(List<ReminderCommon> reminders)
{
    this.Reminders = reminders;

    this.ReminderModel = reminders.First();
}

public ReminderCommon ReminderModel
{
    get
    {
        return this.m_ReminderModel;
    }
    set
    {
        this.m_ReminderModel = value;

        base.OnPropertyChanged("ReminderModel");
    }
}

最后,我的看法

<Border BorderThickness="1" Background="Beige" BorderBrush="DarkKhaki" CornerRadius="5">
    <StackPanel Margin="5">
        <TextBlock Text="{Binding ReminderModel.Message}" TextWrapping="NoWrap" Margin="5" FontWeight="Bold"></TextBlock>
        <TextBlock Text="{Binding ReminderModel.DateFormatted}" TextWrapping="NoWrap" Margin="5"></TextBlock>
        <TextBlock Text="{Binding ReminderModel.Patient}" TextWrapping="NoWrap" Margin="5"></TextBlock>
        <TextBlock Text="{Binding ReminderModel.PatientPhoneNumbers}" TextWrapping="Wrap" Margin="5"></TextBlock>
        <TextBlock Text="{Binding ReminderModel.Doctor}" TextWrapping="NoWrap" Margin="5"></TextBlock>
        <CheckBox IsChecked="{Binding ReminderModel.IsCompleted}" Margin="5" />
    </StackPanel>
</Border>
</Border>

我收到异常

notificationsView.Show();

异常详情

at System.Windows.Threading.Dispatcher.VerifyAccess()
at System.Windows.DependencyObject.GetValue(DependencyProperty dp)
at System.Windows.Media.SolidColorBrush.get_Color()
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Primitives.BulletDecorator.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Control.ArrangeOverride(Size arrangeBounds)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.StackPanel.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at MS.Internal.Helper.ArrangeElementWithSingleChild(UIElement element, Size arrangeSize)
at System.Windows.Controls.ContentPresenter.ArrangeOverride(Size arrangeSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Documents.AdornerDecorator.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Controls.Border.ArrangeOverride(Size finalSize)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Window.ArrangeOverride(Size arrangeBounds)
at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
at System.Windows.UIElement.Arrange(Rect finalRect)
at System.Windows.Interop.HwndSource.SetLayoutSize()
at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
at System.Windows.Window.SetRootVisual()
at System.Windows.Window.SetRootVisualAndUpdateSTC()
at System.Windows.Window.SetupInitialState(Double requestedTop, Double requestedLeft, Double requestedWidth, Double requestedHeight)
at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
at System.Windows.Window.CreateSourceWindowDuringShow()
at System.Windows.Window.SafeCreateWindowDuringShow()
at System.Windows.Window.ShowHelper(Object booleanBox)
at System.Windows.Window.Show()
at Dentist.MainWindow.<RibbonWindow_Loaded>b__0() in D:\development\Dental Soft\Lotus\AMS\Dentist\MainWindow.xaml.cs:line 210
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

TargetSite: {Void VerifyAccess()}

我还提到了两件奇怪的事情:这段代码在 Windows 8 中完美运行,但在 Windows 7 和 Windows XP 中不起作用,当我从视图代码中删除 &lt;CheckBox IsChecked="{Binding ReminderModel.IsCompleted}" Margin="5" /&gt; 时。如果我使用&lt;Button /&gt;,也会出现同样的异常(只是控制,没有任何绑定!)

【问题讨论】:

  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 您正在从 bachground 线程创建 WPF 对象(通知视图)?这不应该工作,是吗?
  • 我做了线程前台,但还是同样的问题。
  • 您是否在搜索框中粘贴了异常?这个问题已经被回答了大约一千次……可能一天几次。微软可能应该将答案直接构建到 Visual Studio 中,并让每个人在他们第一次在代码中实例化线程时阅读它......

标签: c# wpf dispatcher


【解决方案1】:

不需要只需要另一个线程来让另一个窗口并行运行。只在后台线程上执行与数据相关的操作,不要在那里创建 GUI 元素。

【讨论】:

    猜你喜欢
    • 2022-01-13
    相关资源
    最近更新 更多