简体   繁体   English

WPF:使用匿名方法的UnauthorizedAccessException

[英]WPF: UnauthorizedAccessException using anonymous methods

Here is the thing, I want to create a simply app that copy many files from one site, and move them to another; 这就是事情,我想创建一个简单的应用程序,从一个站点复制许多文件,并将它们移动到另一个站点; but using async methods and create a new 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 is throw! 抛出UnauthorizedAccessException! It says that I can't access to txtdestino content. 它说我无法访问txtdestino内容。 Some clues? 一些线索?

-------------------------------------------------------------------------------Edited This is the version with all the changes, get the same error :( any clues? -------------------------------------------------- -----------------------------编辑这是包含所有更改的版本,得到同样的错误:(任何线索?

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); File.Copy(txtdestino.Text,Fi.FullName,true); // here the exception is throw //这里的例外是抛出

Calls to UI elements must be done in the UI thread. 必须在UI线程中调用UI元素。 try getting the text value before your loop. 尝试在循环之前获取文本值。

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

If multiple threads try to access (simultaneously) the file at txtdestino.Text - isn't that doomed from the start? 如果多个线程试图(同时)访问txtdestino.Text的文件 - 从一开始就注定不是这样吗? You might want to read the contents into memory first and write from there... 您可能希望先将内容读入内存并从那里写入...

Equally, you are going to hammer the IO; 同样,你要敲打IO; I wonder if a more practical answer (that solves the issue above and below) is to simply do the copies sequentially on the worker. 我想知道一个更实际的答案(解决上面下面的问题)是否只是简单在工人身上做副本。

It also looks like you might actually be pushing all the work here back to the UI thread anyway ...? 它也像你实际上可能推这里所有的工作回到UI线程反正 ...? surely you should do something like: 你当然应该做的事情如下:

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

which: 哪一个:

  • avoids the foreach/capture issue ( Fi is not captured) 避免foreach / capture问题(未捕获Fi
  • reads the path from the UI thread and uses it (captured) on the worker 从UI线程读取路径并在工作线程上使用它(捕获)
  • process each file sequentially to avoid hammering IO 按顺序处理每个文件以避免锤击IO

You also have the foreach/capture issue; 你也有foreach / capture问题; change it to: 将其更改为:

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

The problem is that most likely all the threads are trying to access the last file. 问题是很可能所有线程都试图访问最后一个文件。 No, really. 不完全是。 This is because foreach technically declares the variable ( tmp above) outside the loop; 这是因为foreach 技术上声明了循环的变量(上面的tmp ); and the variable capture rules (used by lambdas / anon-methods) say that therefore this is the same variable (important: lambdas / anon-methods are full lexical closures, and capture the variable , not the value ). 并且变量捕获规则(由lambdas / anon-methods使用)表示因此这是相同的变量(重要的是:lambdas / anon-methods是完整的词法闭包,并且捕获变量 ,而不是 )。

Re-declaring a variable inside the loop changes the scope, and now the lambda / anon-method treats the variable as different per loop iteration. 在循环重新声明变量会改变范围,现在lambda / anon-method将变量视为每循环迭代不同。

If you really want, I could write it out in something that shows the underlying objects involved, but it depends whether you want that level of detail ;p 如果你真的想要,我可以用显示所涉及的底层对象的东西写出来,但这取决于你是否想要那个细节级别; p

You are creating multiple threads(1 for each file you find). 您正在创建多个线程(您找到的每个文件都有1个)。
The problem is that only your main thread can access your form elements, otherwise all the threads would be changing your form elements at the same time. 问题是只有主线程可以访问表单元素,否则所有线程都会同时更改表单元素。

Pass the value of txtdestino.Text to your new thread and you should be fine. 将txtdestino.Text的值传递给新线程,你应该没问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM