WPF:使用匿名方法的 UnauthorizedAccessException

发布于 2024-10-11 16:47:25 字数 2068 浏览 1 评论 0原文

事情是这样的,我想创建一个简单的应用程序,从一个站点复制许多文件,并将它们移动到另一个站点;但使用异步方法并创建一个新线程。

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!它说我无法访问 txtdestino 内容。一些线索?

-------------------------------------------------- ------------------------------------------已编辑 这是包含所有更改的版本,得到相同的错误:(有任何线索吗?

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); // 这里抛出异常

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! It says that I can't access to txtdestino content. 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); // here the exception is throw

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

得不到的就毁灭 2024-10-18 16:47:25

对 UI 元素的调用必须在 UI 线程中完成。尝试在循环之前获取文本值。

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

Calls to UI elements must be done in the UI thread. try getting the text value before your loop.

string txt = txtdestino.Text;
foreach (FileInfo Fi in _FileInfoArray)
{
    ....
    File.Copy(txt, Fi.FullName, true);
固执像三岁 2024-10-18 16:47:25

如果多个线程尝试(同时)访问 txtdestino.Text 处的文件 - 难道这从一开始就注定失败吗?您可能想首先将内容读入内存,然后从那里写入...

同样,您将要对 IO 进行锤击;我想知道是否更实际的答案(解决上面下面的问题)是简单地按顺序在工作线程上进行复制。

看起来您实际上可能会将此处的所有工作推回 UI 线程无论如何...?当然你应该这样做:

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:

  • 避免 foreach/capture 问题(Fi 未捕获)
  • 从 UI 线程读取路径并在工作
  • 进程中按顺序使用(捕获)每个文件以避免锤击 IO

你也有 foreach/capture 问题;将其更改为:

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

问题是很可能所有线程都试图访问最后文件。不,真的。这是因为 foreach 技术上在循环外部声明了变量(上面的tmp);变量捕获规则(由 lambdas / anon-methods 使用)表示,因此这是相同变量(重要:lambdas / anon-methods 是完整的词法闭包,并捕获 variable< /em>,而不是)。

在循环内重新声明变量会更改范围,现在 lambda / 匿名方法将变量视为每次循环迭代都不同。

如果您确实想要,我可以将其写成显示所涉及的底层对象的内容,但这取决于您是否需要这种详细程度;p

If multiple threads try to access (simultaneously) the file at txtdestino.Text - isn't that doomed from the start? You might want to read the contents into memory first and write from there...

Equally, you are going to hammer the 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...? 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)
  • reads the path from the UI thread and uses it (captured) on the worker
  • process each file sequentially to avoid hammering IO

You also have the foreach/capture issue; 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; 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).

Re-declaring a variable inside the loop changes the scope, and now the lambda / anon-method treats the variable as different per loop iteration.

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

颜漓半夏 2024-10-18 16:47:25

您正在创建多个线程(您找到的每个文件有一个线程)。
问题是只有您的主线程可以访问您的表单元素,否则所有线程都会同时更改您的表单元素。

将 txtdestino.Text 的值传递给您的新线程,您应该没问题。

You are creating multiple threads(1 for each file you find).
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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文