Silverlightでのファイル処理に関する特定の知識を主張することはできませんが、WPFアプリケーションのワーカースレッドでの長いタスクに使用するパターンは次のとおりです。クイックテストのSilverlightプロジェクトでは問題なく動作するようです。
スレッド間でストリームを渡そうとしないようにします。代わりに、バックグラウンドタスクに必要なパラメーターのセットを作成し、それらをスレッドに渡すためのオブジェクトを作成します。バックグラウンドスレッドにファイルを開かせます。したがって、圧縮するファイルを検索するためのフォルダーと、zipを配置するための出力場所が必要な場合は、次のように宣言できます。
class TaskStartupInfo
{
public string SourceFolder { get; set; }
public string TargetFile { get; set; }
}
次に、このクラスのインスタンスを作成し、それをバックグラウンドタスクに渡すことができます。
private void startTaskButton_Click(object sender, RoutedEventArgs e)
{
TaskStartupInfo tsi = new TaskStartupInfo()
{
SourceFolder = @"C:\Some\Folder\",
TargetFile = @"C:\AnotherFolder\data.zip"
};
ThreadPool.QueueUserWorkItem(o => longRunningProcess(tsi));
}
あなたの場合、パスはメインUIスレッドで実行するSaveFileDialogから取得できます。これは、そのスレッドが作業の大部分の実行に縛られることはないためです。その後longRunningProcess()
、メソッドはデータを取得して操作できます。
private void longRunningProcess(object o)
{
TaskStartupInfo tsi = o as TaskStartupInfo;
int taskLength = calculateTaskLength()
// open any files required
this.Dispatcher.BeginInvoke(() => { progressBar1.Value = 0; progressBar1.Maximum = taskLength; });
for (int i = 0; i < taskLength; i++ )
{
doSomethingSlow();
this.Dispatcher.BeginInvoke(() => progressBar1.Value += 1);
}
// close / dispose files
}
progressBar1
Dispatcherオブジェクトを使用してデリゲートを実行することにより、UIオブジェクト(この場合)にアクセスする試みがどのように行われるかに注意してください。このディスパッチャは、UIオブジェクトがUIスレッドによってのみ更新されるようにする問題を扱います。これにより、タスクの各フラグメントが完了した後、プログレスバーが確実に更新されます。
編集: OPのコメントに基づいて、さらに掘り下げてみると、Silverlightのセキュリティサンドボックスは、デスクトップWPFアプリケーションでは課されていないファイルアクセスに制限を課していることがわかります。
分離ストレージの外部でファイルシステムに書き込むには、Silverlightアプリを昇格して実行する必要があります。これは、プロジェクトプロパティの一部として構成できます。プロパティのSilverlightタブに[ブラウザの不足を有効にする]チェックボックスがあり、有効にすると、下の[ブラウザの設定が不足しています]ボタンを開くことができます。 [ブラウザの外部で実行する場合は昇格された信頼が必要]チェックボックスが付いたその他のオプションダイアログ。私はそれをテストしていませんが、そのオプションは確かにブラウザ内で高い信頼を得られないように聞こえます-したがって、コードのセキュリティエラーをチェックし、発生した場合は低い信頼の状況を処理することはおそらく理にかなっています。
この設定を有効にすると、通常のストリームを使用してユーザーのライブラリ内のファイルにアクセスできるようになりますが、ファイルシステムの他の場所ではアクセスできなくなります。デフォルトではOpenFileDialog
、SaveFileDialog
クラスは質問に示されているようにストリームを返しますが、どちらも必要に応じてストリームではなくファイル名にアクセスできます。ファイルを開くと、ファイル名は下に隠されます
myOpenFileDialog.File.FullName
そして節約のためにあなたは使うことができるように見えます
mySaveFileDialog.SafeFileName
代わりは。
したがって、次のコードは、昇格されたOut-of-Browserアプリで機能します。
private void start_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog sfd = new SaveFileDialog();
if (sfd.ShowDialog() != true)
{
return;
}
TaskStartupInfo tsi = new TaskStartupInfo()
{
SourceFolder = @"C:\Users\MyUser\Documents\Information",
TargetFile = sfd.SafeFileName
};
ThreadPool.QueueUserWorkItem(o => longRunningProcess(tsi));
}
private void longRunningProcess(object o)
{
TaskStartupInfo tsi = o as TaskStartupInfo;
var files = Directory.EnumerateFiles(tsi.SourceFolder);
int taskLength = files.Count();
this.Dispatcher.BeginInvoke(() => { progressBar1.Value = 0; progressBar1.Maximum = taskLength; });
using (StreamWriter fs = new StreamWriter(tsi.TargetFile))
{
foreach(string file in files)
{
fs.WriteLine(file);
doSomethingSlow();
this.Dispatcher.BeginInvoke(() => progressBar1.Value += 1);
}
}
}
そして、それはあなたにファイルアクセスとバックグラウンドでファイルを処理するための正しく更新されたプログレスバーの両方を与えます。