Question

J'ai une application Windows Forms, avec un bouton - sur le gestionnaire d'événements du bouton, je dois télécharger un fichier avec SaveFileDialog. Mais je dois le faire de manière asynchrone sur un thread séparé.

Jusqu'à présent, j'ai proposé ce code, mais je ne sais pas si mon approche est défaillante ou correcte:

        private void btnDownload_Click(object sender, EventArgs e)
        {
                ThreadStart tStart = new ThreadStart(DoWorkDownload);
                Thread thread = new Thread(tStart);
                thread.SetApartmentState(ApartmentState.STA);
                thread.Start();
        }

        private void DoWorkDownload()
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.InitialDirectory = "C:\\";
            sfd.Filter = "All files (*.*)|*.*";
            sfd.FilterIndex = 1;
            sfd.RestoreDirectory = true;

            if (sfd.ShowDialog() == DialogResult.OK)
            {
            //do file saving here
            }
        }
}

Dans le code ci-dessus, ma logique est la suivante: cliquez sur le bouton, créez un nouveau thread, transmettez la méthode DoWorkDownload () au thread, puis démarrez-la; à ce moment, il est supposé entrer dans la méthode de travail - cependant, lors du débogage, il n'entre jamais dans DoWorkDownload ().

Est-ce que quelqu'un sait ce que je manque?

Merci.

Était-ce utile?

La solution

Vous pouvez utiliser le BackgroundWorker , qui est facile à utiliser.

De plus, je ne suis pas sûr qu'il soit tout à fait sûr (je peux toutefois me tromper) d'afficher SaveFileDialog dans le nouveau fil de discussion. Ma recommandation serait un flux en tant que tel:

  1. Afficher SaveFileDialog sur le thread principal.
  2. Transmettez le nom du fichier à une méthode, qui est ensuite appelée de manière asynchrone.

Voici un exemple de mise en oeuvre, sans l'utilisation de BackgroundWorker :

private void button1_Click(object sender, EventArgs e)
{
  SaveFileDialog sfd = new SaveFileDialog();
  sfd.InitialDirectory = "C:\\";
  sfd.Filter = "All files (*.*)|*.*";
  sfd.FilterIndex = 1;
  sfd.RestoreDirectory = true;
  if (sfd.ShowDialog() == DialogResult.OK)
  {
    // Invoke the SaveFile method on a new thread.
    Action<string> invoker = new Action<string>(SaveFile);
    invoker.BeginInvoke(sfd.FileName, OnSaveFileCompleted, invoker);
  }
}

protected void SaveFile(string fileName)
{
  // save file here (occurs on non-UI thread)
}

protected void OnSaveFileCompleted(IAsyncResult result)
{
  Action<string> invoker = (Action<string>) result.AsyncState;
  invoker.EndInvoke(result);
  // perform other actions after the file has been saved (also occurs on non-UI thread)
}

Notez que toutes les actions effectuées sur des threads non-UI ne doivent affecter que des éléments non-UI. Si vous souhaitez modifier des éléments d'interface utilisateur, vous devez réorganiser l'appel vers le thread d'interface utilisateur en utilisant Control.Invoke (par exemple, this.Invoke ). Voir cet article pour plus de détails.

Autres conseils

Dans mon cas, le débogueur DO entre DoWorkDownload () Il entre après la fin de btnDownload_Click () Définir un point d'arrêt sur SaveFileDialog sfd = new SaveFileDialog (); et ça devrait marcher

Pour prouver que cela fonctionne de manière asynchrone, j'ai même mis le code suivant

ThreadStart tStart = new ThreadStart(DoWorkDownload);
Thread thread = new Thread(tStart);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();

Thread.Sleep(10000);
MessageBox.Show("qwe");

et exécutez sans le débogueur et vous verrez que lorsque le thread actuel se mettra en veille, SaveFileDialog apparaîtra ... et qu'après 10 secondes, une boîte de message s'affichera

Bernhof a peut-être raison, mais soyez prudent. Tous les éléments de l'interface utilisateur doivent s'exécuter sur le même thread. Donc, si vous créez un nouveau thread pour le SFD, assurez-vous de ne mettre à jour aucun contrôle de votre fenêtre principale.

Cordialement, Guillaume Hanique

dans votre classe

private object sync_temp = new object();

et dans la méthode du fil

SaveFileDialog save = new SaveFileDialog();
// your code to do with "save"
Action ac = () => { lock (sync_temp) { save.ShowDialog(); } };
Invoke(ac);
//Thread.Sleep(10);
lock (sync_temp)
{
   string path = save.FileName;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top