1

I have a WPF application that uses multi-threading to perform notifications. But I've faced the problem with "The calling thread cannot access this object because a different thread owns it." exception.

When my main window is loaded I create a new thread for notification window

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();
}

Constructor for view is default:

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

Constructor for view model and model to bind

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");
    }
}

Finally, my view

<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>

I receive exception on

notificationsView.Show();

Exception details

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()}

Also I mentioned two strange things: this code perfectly works in Windows 8, but doesn't work in Windows 7 and Windows XP and when I delete <CheckBox IsChecked="{Binding ReminderModel.IsCompleted}" Margin="5" /> from view code works. The same exceptions occurs if I use <Button /> (just control, without any bindings!)

John Saunders
  • 160,644
  • 26
  • 247
  • 397
Pylyp Lebediev
  • 1,991
  • 4
  • 26
  • 44
  • possible duplicate of [How to deal with cross-thread access exceptions?](http://stackoverflow.com/questions/11923865/how-to-deal-with-cross-thread-access-exceptions) – H.B. Aug 20 '13 at 19:54
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Aug 20 '13 at 19:57
  • You are creating WPF objects (the notification view) from a bachground thread? That's not supposed to work, is it? – oddparity Aug 20 '13 at 19:57
  • I've made the thread foreground, but still the same problem. – Pylyp Lebediev Aug 20 '13 at 20:03
  • Did you paste the exception in the search box? This question has been answered about a thousand times... probably several times a day. Microsoft should probably build the answer right into Visual Studio and make everyone read it the first time they instantiate a thread in their code... – J... Aug 20 '13 at 20:06
  • :) Of course, I've looked for such problems. I don't see the place where I try to change UI content from another thread. And I cannot understand, how or (just or without any binding) influence on this exception. If there are no such elements on the view everything is OK. – Pylyp Lebediev Aug 20 '13 at 20:21
  • The view has UI elements. You can only create UI elements on the main thread. You can create data in the backgound and then bind that data to the UI elements. – paparazzo Aug 20 '13 at 20:45

1 Answers1

0

You do not need another thread just to have another window running in parallel. Only do data-related actions on a background thread, do not create GUI elements there.

H.B.
  • 166,899
  • 29
  • 327
  • 400