Question

Voici la chose, je veux créer une application simplement que copier plusieurs fichiers d'un site, et les déplacer à un autre; mais en utilisant des méthodes de async et de créer un nouveau thread.

private void button3_Click(object sender, RoutedEventArgs e)
{

    //progressBar1.Maximum = _FileInfoArray.Count;

    DispatcherTimer dt1 = new DispatcherTimer();
    foreach (FileInfo Fi in _FileInfoArray)
    {
        Thread t = new Thread(new ThreadStart(delegate()
        {
            DispatcherOperation _dispOp = progressBar1.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(delegate()
            {

                File.Copy(txtdestino.Text, Fi.FullName, true);

                //progressBar1.Value = n;
                //txtstatus.Content = ("Copiados " + n.ToString() + " archivos");
                //Thread.Sleep(100);
            }
            ));
            _dispOp.Completed += new EventHandler(_dispOp_Completed);
        }
            ));
        t.Start();
    }
}

UnauthorizedAccessException est un jet! Il dit que je ne peux pas accéder à txtdestino contenu. Quelques indices?

----------------------------------------------- --------------------------------Édité Ceci est la version avec tous les changements, obtenir la même erreur :( tous les indices?

private void button4_Click(object sender, RoutedEventArgs e)
{
    //First: Build mynames
    List<string> mynames = new List<string>();
    foreach (FileInfo fi in _FileInfoArray)
    {
        mynames.Add(fi.FullName);
    }



    Thread t = new Thread(new ThreadStart(delegate()
       {
          foreach (string fullname in mynames)
            {
            DispatcherOperation _dispOp = progressBar1.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(delegate()
            {
                string destino = System.IO.Path.Combine(@"C:\", System.IO.Path.GetFileName(fullname));
                File.Copy(fullname, destino, true);
                //Some progressbar changes
            }
            ));
            _dispOp.Completed += new EventHandler(_dispOp_Completed);
          }
        }
                ));
        t.Start();
    }

File.Copy (txtdestino.Text, Fi.FullName, true); // ici l'exception est de lancer

Était-ce utile?

La solution

Si plusieurs threads tentent d'accéder (en même temps) le fichier à txtdestino.Text - est pas condamné dès le départ? Vous pouvez lire le contenu en mémoire premier et écrire à partir de là ...

De même, vous allez marteler le IO; Je me demande si une réponse plus pratique (qui permet de résoudre la question ci-dessus et ci-dessous) est simplement faire les copies séquentiellement sur le travailleur.

Il semble aussi que vous pourriez vraiment être pousser tout le travail ici au thread de l'interface utilisateur de toute façon ...? sûrement vous devriez faire quelque chose comme:

string path = txtdestino.Text;
Thread t = new Thread(new ThreadStart(delegate() {
    foreach (FileInfo Fi in _FileInfoArray) {
        File.Copy(path, Fi.FullName, true);
    }
}));
t.Start();

qui:

  • évite la question foreach / capture (Fi est pas capturé)
  • lit le chemin du thread d'interface utilisateur et l'utilise (capture) sur le travailleur
  • traiter séquentiellement chaque fichier pour éviter martelage IO

Vous avez aussi la question foreach / capture; changer à:

foreach (FileInfo tmp in _FileInfoArray)
{
    FileInfo Fi = tmp;
    ...

Le problème est que le plus probable tous les fils tentent d'accéder au fichier dernier . Pas vraiment. En effet, foreach techniquement déclare la variable (tmp ci-dessus) la boucle extérieur ; et les règles de capture variable (utilisés par les lambdas / anon-méthodes) disent que, par conséquent c'est le même variable (importante: lambdas / anon-méthodes sont des fermetures lexicales complètes, et capturer les variable , pas la valeur ).

Re-déclaration d'une variable dans la boucle change le champ d'application, et maintenant le lambda / anon-méthode traite la variable différente par itération de la boucle.

Si vous vraiment veux, je pourrais écrire dans quelque chose qui montre les objets sous-jacents impliqués, mais cela dépend si vous voulez que le niveau de détail; p

Autres conseils

Les appels à des éléments interface utilisateur doit être fait dans le thread d'interface utilisateur. essayez d'obtenir la valeur de texte avant votre boucle.

string txt = txtdestino.Text;
foreach (FileInfo Fi in _FileInfoArray)
{
    ....
    File.Copy(txt, Fi.FullName, true);

Vous créez plusieurs threads (1 pour chaque fichier que vous trouvez).
Le problème est que seul votre thread principal peut accéder à vos éléments de formulaire, sinon tous les fils seraient en train de changer vos éléments de formulaire en même temps.

Passez la valeur de txtdestino.Text à votre nouveau thread et vous devriez être bien.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top