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()
方法は、データを取得し、それに取り組むことができます:UIオブジェクト(この場合はprogressBar1
)にアクセスしようとするが、デリゲートを実行するために、ディスパッチャオブジェクトを使用することによってどのように行われるか
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
}
注意。このディスパッチャは、UIオブジェクトがUIスレッドによってのみ更新されることを保証するという問題を扱います。タスクの各断片が完了した後、プログレスバーが確実に更新されるようにする必要があります。
編集: OPのコメントに基づいて、およびいくつかの更なる掘削が行われた、私は、Silverlightのセキュリティサンドボックスは、デスクトップWPFアプリケーションで課されていないファイルへのアクセスに制限を課していることがわかります。
Isolated Storage以外のファイルシステムに書き込むには、実際にSilverlightアプリケーションを昇格させて実行する必要があります。これはプロジェクトプロパティの一部として設定することができます。プロパティの[Silverlight]タブにある[ブラウザの不足を有効にする]チェックボックスがあり、その下にある[ブラウザの設定を外す]ボタンを有効にすると、 「ブラウザの外で実行したときに昇格された信頼を必要とする」チェックボックスがあるその他のオプションダイアログ。私はそれをテストしていませんが、そのオプションは確かにあなたがブラウザ内で信頼を得ることができないように思えます - したがって、コード内のセキュリティエラーをチェックし、
この設定を有効にすると、通常のストリームを使用して、ユーザーのライブラリ内のファイルにアクセスできますが、ファイルシステムの他の場所にはアクセスできないようです。デフォルトでは、OpenFileDialog
とSaveFileDialog
クラスは質問に含意されているようにストリームを返しますが、両方ともストリームではなくファイル名にアクセスできます。ファイルを開くときにファイル名が
myOpenFileDialog.File.FullName
の下に隠され、保存のために、あなたは代わりに
mySaveFileDialog.SafeFileName
を使用することができるように思われます。
だから、次のコードでは、高架アウトオブブラウザアプリで作業することができます:
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);
}
}
}
そして、それはあなたのファイルアクセスとbackgrond内のファイルの処理のために正しく更新プログレスバーの両方を提供します。
私は高性能パーミッションでSLアプリを走らせなければならないと思うと思います。問題は、SLの 'SaveFileDialog'は私がアクセスできるパスを提供せず、ユーザーが指定したストリームだけです - そうでなければ私はZIPを使用しないことになります(これは事実上すべてのイメージのコンテナです)ファイルを直接パスに書き込むだけです。私が昇格すれば、ユーザーライブラリのフォルダに徹底的にアクセスできます。 –
元気いっぱい - 私はもともと高揚して走っていることを嫌っていましたが、状況によってはこれは愚かなようです。しかし、私はzipファイル全体を削除して、ユーザーのマイピクチャフォルダのフォルダに直接画像を書き込むことができます。 –