Bonjour,
Je réalise une première application WPF, notamment pour me familiariser à la "bête". C'est une sorte de Flickr Uploader (pour ceux qui connaissent) c'est-à-dire une application dans laquelle on charge des photos et on édite des tags exif avant de publier le tout sur le site cible.
Pour afficher les miniatures des images à publier, j'ai réalisé un UserControl qui affiche une miniature de la photo ainsi que le nom du fichier.
Maintenant je souhaite rendre l'application plus "user-friendly" en faisant en sorte d'informer l'utilisateur de l'état de chargement des photos dans l'interface. Dans d'autres applications Winforms, j'avais utilisé le BackgroundWorker qui fonctionne parfaitement, pour peu que le thread principal ait l'attribut STAThread.
J'ai implémenté mon BackgroundWorker de la manière suivante :
J'ai bien vérifié par ailleurs que le thread principal était en mode STA :
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 // La classe de la fenêtre principale public partial class FenetrePrincipale : Window { private BackgroundWorker _ChargementPhotosDansInterface = new BackgroundWorker(); } public FenetrePrincipale() { InitializeComponent(); InitialisationBackgroundWorker(); } // Abonnement du BGW aux délégués pour le traitement de l'avancement private void InitialisationBackgroundWorker() { _ChargementPhotosDansInterface.DoWork += new DoWorkEventHandler(_ChargementPhotosDansInterface_DoWork); _ChargementPhotosDansInterface.ProgressChanged += new ProgressChangedEventHandler(_ChargementPhotosDansInterface_ProgressChanged); _ChargementPhotosDansInterface.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_ChargementPhotosDansInterface_RunWorkerCompleted); } void _ChargementPhotosDansInterface_DoWork(object sender, DoWorkEventArgs e) { // Appel de la méthode coûteuse en temps et ressources PopulationImages((string[])e.Argument); } void _ChargementPhotosDansInterface_ProgressChanged(object sender, ProgressChangedEventArgs e) { // Mise à jour de l'avancement pour l'utilisateur } void _ChargementPhotosDansInterface_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { // Code à exécuter lorsque c'est terminé } // Itère sur les noms de fichiers choisis pour générer le usercontrol correspondant et l'ajouter au WrapPanel qui les affiche. private void PopulationImages(string[] NomsFichiers) { foreach (string Fichier in NomsFichiers) { PhotoAPublier Photo = new PhotoAPublier(Fichier, this); Wrp_Photos.Children.Add(Photo); } }
Fichier app.g.cs :
Tout cela compile correctement. Cependant, à l'exécution, j'obtiens l'erreur suivante lors de la tentative d'instanciation du premier usercontrol :
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 /// <summary> /// App /// </summary> public partial class App : System.Windows.Application { /// <summary> /// InitializeComponent /// </summary> [System.Diagnostics.DebuggerNonUserCodeAttribute()] public void InitializeComponent() { #line 4 "..\..\App.xaml" this.StartupUri = new System.Uri("FenetrePrincipale.xaml", System.UriKind.Relative); #line default #line hidden } /// <summary> /// Application Entry Point. /// </summary> [System.STAThreadAttribute()] [System.Diagnostics.DebuggerNonUserCodeAttribute()] public static void Main() { Publication_photos.App app = new Publication_photos.App(); app.InitializeComponent(); app.Run(); } } }
L'état de la pile si ça peut servir :L'exception System.InvalidOperationException n'a pas été gérée par le code utilisateur
Message="Le thread appelant doit être en mode STA, comme l'exigent de nombreux composants de l'interface utilisateur."
Pourquoi cette exception? Mon thread principal est pourtant en mode STA... Que dois-je faire pour que cela fonctionne? J'ai commencé à regarder ce qui semble être une solution avec le Dispatcher, mais si tel est le cas je n'ai pas réussi à comprendre comment l'invoquer correctement pour lancer mon thread de travail de façon correcte.Source="PresentationCore"
StackTrace:
à System.Windows.Input.InputManager..ctor()
à System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
à System.Windows.Input.InputManager.get_Current()
à System.Windows.Input.KeyboardNavigation..ctor()
à System.Windows.FrameworkElement.FrameworkServices..ctor()
à System.Windows.FrameworkElement.EnsureFrameworkServices()
à System.Windows.FrameworkElement..ctor()
à System.Windows.Controls.Control..ctor()
à System.Windows.Controls.UserControl..ctor()
à Publication_photos.PhotoAPublier..ctor(String CheminFichier, FenetrePrincipale FenetreEnCours) dans I:\Programmation\DotNet\Sources\Client lourd\PublicationPhotos\Publication photos\Publication photos\PhotoAPublier.xaml.cs:ligne 34
à Publication_photos.FenetrePrincipale.PopulationImages(String[] NomsFichiers) dans I:\Programmation\DotNet\Sources\Client lourd\PublicationPhotos\Publication photos\Publication photos\FenetrePrincipale.xaml.cs:ligne 92
à Publication_photos.FenetrePrincipale._ChargementPhotosDansInterface_DoWork(Object sender, DoWorkEventArgs e) dans I:\Programmation\DotNet\Sources\Client lourd\PublicationPhotos\Publication photos\Publication photos\FenetrePrincipale.xaml.cs:ligne 46
à System.ComponentModel.BackgroundWorker.OnDoWork(DoWorkEventArgs e)
à System.ComponentModel.BackgroundWorker.WorkerThreadStart(Object argument)
InnerException:
Toutes vos lumières sont les bienvenues !
Cordialement,
Nixar
Partager