2011-01-11 4 views
1

Voici la chose, je veux créer une application simple qui copie beaucoup de fichiers d'un site, et les déplace à un autre; mais en utilisant des méthodes async et créer un nouveau thread.WPF: UnauthorizedAccessException utilisant des méthodes anonymes

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 is throw! Il dit que je ne peux pas accéder au contenu de txtdestino. 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

+0

Où le code lance-t-il l'exception? –

Répondre

1

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

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

Il semblerait aussi que vous pourriez en fait repousser tout le travail sur le fil d'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 n'est pas capturé)
  • lit le chemin du thread d'interface utilisateur et l'utilise (capture) sur le travailleur
  • de processus
  • chaque séquence de fichiers pour éviter martelage IO

Vous avez également le problème foreach/capture; changer pour:

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

Le problème est que le plus probable tous les fils tentent d'accéder au dernier fichier . Pas vraiment. C'est parce que foreachtechniquement déclare la variable (tmp ci-dessus) en dehors de la boucle; et les règles de capture variables (utilisés par les lambdas/anon-méthodes) disent que, par conséquent ce sont les mêmes variables (important: lambdas/anon-méthodes sont des fermetures lexicales complètes et saisir la variable , pas la valeur ) . Re-déclarer une variable à l'intérieur de la boucle change la portée, et maintenant la méthode lambda/anon traite la variable comme différente par itération de boucle.

Si vous vraiment voulez, 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

+0

Édité! Je pense que tu peux m'aider, ça me rend fou. –

+0

@Diego - question stupide, mais * l'utilisateur at-il l'autorisation d'écrire à cet emplacement cible *? Et lire de la source? –

+0

bien sûr, nous parlons du bureau de mon pc! quelques suggestions? –

1

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 threads changeraient vos éléments de formulaire en même temps. Transmettez la valeur de txtdestino.Text à votre nouveau thread et tout devrait bien se passer.

+0

maintenant, quelques indices? –

2

Les appels aux éléments d'interface utilisateur doivent être effectués dans le thread d'interface utilisateur. essayez d'obtenir la valeur du texte avant votre boucle.

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

maintenant, quelques indices? –

+0

vous devez supprimer l'un des appels ui de l'un de ces délégués qui sera exécuté dans un autre thread. Aucun contrôle ui ne doit être référencé depuis l'intérieur de ce code, donc pas de référencement de la zone de texte ou des barres de progression/etc sans les appels 'Dispatcher.Invoke' (ou connexes) qui les entourent! –

+0

Il n'y a plus d'appels ui. merci –

Questions connexes