Modifier un contrôle depuis un autre thread en WPF

Dans une application WPF, l’utilisation de plusieurs **threads **pour la modification de contrôles est plus compliquée qu’il n’y parait. Un contrôle ne peut être modifier que par le thread à qui il appartient.

Par exemple :

  • MainWindow.xaml
<Window x:Class="Threads.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
  <Grid>
    <Label Content="Label" Height="28" HorizontalAlignment="Left" Name="label1" />
  </Grid>
</Window>
  • MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;

namespace Threads
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Create Thread
            Thread myThread = new Thread(ModifyLabel);
    
            // Start Thread
            myThread.Start();
    
            // Wait for 3sec
            Thread.Sleep(3000);
    
            // Stop Thread
            myThread.Abort();
        }
    
        public void ModifyLabel()
        {
            label1.Content = "my content";
        }
    }
}

Lorsqu’on lance ce programme l’erreur suivante apparait :

The calling thread cannot access this object because a different thread owns it.

En fait le **Label **n’appartient pas à notre **thread **myThread.

Pour pallier à ce problème, il faut utiliser le **Dispatcher **du contrôle comme ci-dessous

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;

namespace Threads
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // Create Thread
            Thread myThread = new Thread(ModifyLabel);
    
            // Start Thread
            myThread.Start();
    
            // Wait for 3sec
            Thread.Sleep(3000);
    
            // Stop Thread
            myThread.Abort();
        }
    
        public void ModifyLabel()
        {
            label1.Dispatcher.Invoke(
            System.Windows.Threading.DispatcherPriority.Normal,
            new Action(
            delegate()
            {
                label1.Content = "my content";
                label1.FontSize = 10;
            }
            ));
        }
    }
}
WPF