Problème de STAThread en WPF
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 :
Code:
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);
}
} |
J'ai bien vérifié par ailleurs que le thread principal était en mode STA :
Fichier app.g.cs :
Code:
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();
}
}
} |
Tout cela compile correctement. Cependant, à l'exécution, j'obtiens l'erreur suivante lors de la tentative d'instanciation du premier usercontrol :
Citation:
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."
L'état de la pile si ça peut servir :
Citation:
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:
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.:?
Toutes vos lumières sont les bienvenues !:ccool:
Cordialement,
Nixar