長い投稿にはお詫び申し上げます。メインスレッドでユーザーが作業中に、バックグラウンドスレッドでオブジェクトを処理する
私は多くの要素を含むクラス(SceneryFileと呼ばれる)を持っています。ユーザーは2Dインターフェイスを使用して、このクラスの内容を変更します。結果は、Flight Simulatorアプリケーションで使用されるファイルにコンパイルされます。ユーザアクションは、コンパイルが失敗するエラー、またはコンパイルが成功する警告を結果として出すことができますが、結果はシミュレータで正しく機能しません。私はReSharperやJust Codeのようなある程度のプログラムを複製して、ユーザーが作業中やエラーを報告している間にSceneryFileの状態をバックグラウンドでチェックしたいと考えています。バックグラウンドワーカーを使用してこれを実行しようとしましたが、結果は信頼できません。
まず私はsceneryfileインスタンスおよびいくつかの他のものが含まれているバックグラウンドワーカーに渡す引数のセットを作成しました:
public class FSIssueArgs {
public FSIssueArgs(SceneryFile sceneryFile, Airport airport) {
Issues = new Dictionary<string, FSIssue>();
SceneryFile = sceneryFile;
Airport = airport;
}
public FSIssueSeverity Severity { get; set; }
public Dictionary<string, FSIssue> Issues { get; set; }
public SceneryFile SceneryFile { get; private set; }
public Airport Airport { get; private set; }
}
は、私は、バックグラウンドワーカーにそれが終了するたびに実行しています。ファイルがロードされるとissueStatusLevelが存在するエラーと警告に基づいて色を示したボタンである私は、バックグラウンドワーカーをキックオフし、それが完了したイベント
private void onIssuesBackgroundWorkerRunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e) {
var args = e.Result as FSIssueArgs;
if (args != null) {
issueStatusLevel.BackColor = args.SceneryFile.IssueStatusFlag();
G.SceneryFile.Issues = args.Issues;
}
G.IssueHandlerActive = false;
check4Issues();
}
に再び実行されます。これをクリックすると、見つかった問題を一覧表示するダイアログが開きます。
check4Issuesインジケータボタンの色が確実に動作しますが、問題のリストが確実に報告されませんバックグラウンドワーカー
private void check4Issues() {
if (G.IssueHandlerActive) return;
G.IssueHandlerActive = true;
issuesFound = new Dictionary<string, FSIssue>();
var issueArgs = new FSIssueArgs(G.SceneryFile, G.CurrentAirport);
issuesBackgroundWorker.RunWorkerAsync(issueArgs);
}
を実行するための呼び出しが含まれています。ボタンをクリックしてリストダイアログが開いている場合、バックグラウンドワーカーの実行を停止します。
問題は、主ワーカースレッドとバックグラウンドワーカースレッドの間でオブジェクトがどのように渡されるかわかりません。私はbakgroundスレッドに渡されたオブジェクト(SceneryFile)が単なる参照ではなくコピーであることを期待しました。このファイルのメソッドを実行してエラーをチェックします。エラーはファイルに保存されます。私はe.Resultのargsの一部としてファイルを送り返します。私は今、間違っていると思っています。何とか2つのスレッドで同じオブジェクトを使用するべきではありません。
もちろん、ファイルがバックグラウンドで検証されている間、ユーザーはフォアグラウンドでファイルを変更しています。
私がしたいことは、処理されたバックグラウンドスレッドにファイルのコピーを送信することですが、メインスレッドのファイルへの参照ではありません。処理されたら、問題のリストを送り返したいと思います。その間にユーザーがファイルを変更した可能性があることを認識していますが、あまり心配していないので、次回の実行でそれをキャッチします。
ファイルのクリティカルビットは、すべて基本クラスから継承したアイテムのコレクションです。私はそれを永続化するためにディスクにシリアル化しますが、それは高価で時間がかかります - この操作の鍵はスピードです。大きなファイルは分析に数秒かかることがあります。それは私の貧しいプログラミングかもしれません....私は、メモリストリームにシリアル化すると、はるかに高速になると思いますか? – ScruffyDuck
確かに、私が提供するソリューションを選択した場合は、あなたはまたconcurent acessを処理する必要があります。ファイルの大きさによって異なります。 – Tigran
私はストリームを使用するという考えは良いと思います!しかし、最終的に私はバックグラウンドタスクの完了時にSceneryFileへの依存を取り除いて問題を解決し、返された新しいリストに問題を連載しました。これは信頼できると思われる – ScruffyDuck