1

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

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

4

3 回答 3

2

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

string txt = txtdestino.Text;
foreach (FileInfo Fi in _FileInfoArray)
{
    ....
    File.Copy(txt, Fi.FullName, true);
于 2011-01-11T07:20:39.103 回答
1

如果多个线程尝试(同时)访问该文件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();

哪个:

  • 避免了 foreach/capture 问题(Fi未捕获)
  • 从 UI 线程读取路径并在工作线程上使用(捕获)
  • 依次处理每个文件以避免锤击 IO

您还有 foreach/capture 问题;将其更改为:

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

问题是很可能所有线程都在尝试访问最后一个文件。不完全是。这是因为foreach 技术上在循环声明了变量(tmp上面) ;并且变量捕获规则(由 lambdas / anon-methods 使用)说因此这是同一个变量(重要:lambdas / anon-methods 是完整的词法闭包,并捕获variable,而不是value)。

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

如果你真的想要,我可以把它写成显示所涉及的底层对象的东西,但这取决于你是否想要那个级别的细节;p

于 2011-01-11T07:14:09.853 回答
1

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

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

于 2011-01-11T07:18:55.520 回答