WPF:匿名のメソッドを使用したUnauthorizedAccesSexception
-
09-10-2019 - |
質問
ここにありますが、あるサイトから多くのファイルをコピーして別のファイルに移動する単純なアプリを作成したいと思います。ただし、ASYNCメソッドを使用して新しいスレッドを作成します。
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); //ここで例外はスローです
解決
複数のスレッドが(同時に)アクセスしようとする場合、 txtdestino.Text
- それは最初から運命づけられていませんか?内容をメモリに読みたいと思うかもしれません 最初 そこから書きます...
同様に、あなたはIOをhammerするつもりです。もっと実用的な答え(上記の問題を解決するのだろうか と 以下)は、単にコピーを行うことです 順次 労働者に。
また、ここですべての作業を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は完全な語彙閉鎖であり、 変数, 、ではありません 価値).
変数を再宣言します 中身 ループはスコープを変更し、現在、Lambda / Anon-Methodは変数をループごとの異なる反復として扱います。
もし、あんたが 本当 欲しい、私はそれを関係する基礎となるオブジェクトを示すものでそれを書き出すことができますが、それはあなたがそのレベルの詳細を望むかどうかによって異なります; P
他のヒント
UI要素への呼び出しは、UIスレッドで行う必要があります。ループの前にテキスト値を取得してみてください。
string txt = txtdestino.Text;
foreach (FileInfo Fi in _FileInfoArray)
{
....
File.Copy(txt, Fi.FullName, true);
複数のスレッド(見つけたファイルごとに1)を作成しています。
問題は、メインスレッドのみがフォーム要素にアクセスできることです。そうしないと、すべてのスレッドがフォーム要素を同時に変更することです。
txtdestino.textの値を新しいスレッドに渡すと、問題ありません。