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 /キャプチャの問題を回避します(キャプチャFiされません)
  • UIスレッドからパスを読み取り、ワーカーで使用(キャプチャ)します
  • IOの打撃を避けるために、各ファイルを順番に処理します

foreach/captureの問題もあります。次のように変更します。

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

問題は、ほとんどの場合、すべてのスレッドが最後のファイルにアクセスしようとしていることです。いいえ、本当に。これは、foreach 技術的にはループの外側で変数(tmp上記)を宣言しているためです。変数キャプチャルール(ラムダ/アノンメソッドで使用)は、したがってこれは同じ変数であると言います(重要:ラムダ/アノンメソッドは完全な字句クロージャであり、ではなく変数をキャプチャします)。

ループ内で変数を再宣言するとスコープが変更され、ラムダ/アノンメソッドは変数をループの反復ごとに異なるものとして扱います。

本当に必要な場合は、関連する基になるオブジェクトを示すものに書き出すことができますが、そのレベルの詳細が必要かどうかによって異なります; p

于 2011-01-11T07:14:09.853 に答える
1

複数のスレッドを作成しています(ファイルごとに1つ)。
問題は、メインスレッドのみがフォーム要素にアクセスできることです。そうしないと、すべてのスレッドが同時にフォーム要素を変更することになります。

txtdestino.Textの値を新しいスレッドに渡すと、問題がないはずです。

于 2011-01-11T07:18:55.520 に答える