Bonjour,
J'ai une application multithread avec une interface en WPF. L'interface est géré par ses propres threads, le déroulement de l'application dans d'autres threads.
En utilisant Dispatcher et autre gestion d'Events, j'arrive plutôt pas mal à faire communiquer mes threads d'affichage et mes threads de fonctionnement.
J'ai notamment un thread chargé de faire disparaitre une fenêtre WPF en cas d'inactivité. Pour cela, j'appelle un dispatcher qui s'occupe du Hide().
Tout à l'air de marche pas mal...
Sauf que maintenant, si je reprends EXACTEMENT le même code sur une fenêtre WPF contenant un WindowsFormHost, j'ai une belle InvalidOperationException ( Le thread appelant ne peut pas accéder à cet objet parce qu'un autre thread en est propriétaire.) qui arrive.
J'ai fait une petite application toute bête qui reproduit exactement mon problème. En voici le code :
J'ai commenté au maximum pour que vous compreniez.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 using System.Windows; using System.Threading; using System.Windows.Threading; namespace TEstThread { /// <summary> /// Logique d'interaction pour Window1.xaml /// </summary> public partial class Window1 : Window { Window2 DeuxiemeFenetre; //Une Window WPF classique avec rien de particulier (...mais si on y ajoute un WindowsFormHost, plus rien ne marche) Thread ThreadClignoteur; //Thread qui affiche ou cache la fenetre... Thread Demarrage; //Thread controllant l'ouverture de la fenetre bool clignote = true; /// <summary> /// Constructeur de la fenetre, qui contient juste un bouton Start ( btn_Lancer) et un bouton Stop (btn_Stop) /// </summary> public Window1() { InitializeComponent(); //Initialisation du clignoteur ThreadClignoteur = new Thread(ThreadClignotage); ThreadClignoteur.SetApartmentState(ApartmentState.STA); } /// <summary> /// Lance le thread de clignotement /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_Lancer_Click(object sender, RoutedEventArgs e) { ThreadClignoteur.Start(); } /// <summary> /// Force la fermeture de la fenetre /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btn_Stop_Click(object sender, RoutedEventArgs e) { clignote = false; } /// <summary> /// Clignote : lance le thread qui affiche la fenetre, puis essaie de cacher la fenetre... et recommence /// </summary> private void ThreadClignotage() { while (clignote) { if (DeuxiemeFenetre == null || DeuxiemeFenetre.Visibility != Visibility.Visible) { newThreadFenetre(); } Thread.Sleep(3000); CacherFenetre2(); Thread.Sleep(2000); } } /// <summary> /// Cache la fenetre /// </summary> private void CacherFenetre2() { DeuxiemeFenetre.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate { DeuxiemeFenetre.Hide(); }); } /// <summary> /// Thread gérant l'affichage la fenetre /// </summary> private void newThreadFenetre() { Demarrage = new Thread(StartUI); Demarrage.SetApartmentState(ApartmentState.STA); Demarrage.Start(); } /// <summary> /// Demarre la fenetre /// </summary> public void StartUI() { DeuxiemeFenetre = new Window2(); DeuxiemeFenetre.ShowDialog(); } } }
En gros, si "DeuxiemeFenetre" est une simple fenêtre WPF avec un Label, tout se passe bien.
Maintenant, si je rajoute un WindowsFormHost à cette fenêtre, ça plante...
Qu'ai-je fait de mal ? Comment m'en sortir ?
Partager