對於長帖子的道歉。用戶在主線程中處理後臺線程中的對象
我有一個包含了很多元素的類(稱爲SceneryFile)。用戶使用2D界面來修改此類的內容。結果被編譯爲在Flight Simulator應用程序中使用的文件。用戶操作可能會導致編譯失敗的錯誤,或者警告編譯會成功,但結果在模擬器中不能正常工作。我想複製到某些程度的程序,如ReSharper或Just Code,用戶在工作時檢查SceneryFile的狀態並報告錯誤。我試圖用Background Worker來做這件事,但結果並不可靠。
首先,我創建了一組參數傳遞給包含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; }
}
我每次結束時運行的後臺工作。當加載一個文件,我揭開序幕,後臺工作,然後在完成事件
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();
}
再次運行issueStatusLevel是一個按鈕,顯示基於錯誤和警告存在一個顏色。點擊它會打開一個對話框,列出發現的問題。
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中的參數的一部分發回。我現在認爲我做錯了,不知怎的,我不應該在兩個線程中使用同一個對象。
當然,雖然該文件在用戶正在修改它在前景背景驗證。
所以我想加時賽做的就是發送的文件的副本到被處理,但不是在主線程中的文件的引用後臺線程。當它被處理時,我想發回一個問題清單。我認識到用戶可能在此期間更改了文件,但我並不太在意,下一次運行會趕上它。
該文件的關鍵位是所有從基類繼承的項目的集合。我將它序列化到磁盤上來堅持下去,但這樣很昂貴且耗時 - 這項操作的關鍵是速度。一個大文件可能需要幾秒鐘才能分析。這可能是我糟糕的編程,雖然....我猜串行到內存流可能會快很多? – ScruffyDuck
當然,但如果您選擇由我提供的解決方案,您還應該注意併發連接。取決於你的文件有多大。 – Tigran
我認爲使用流的想法是一個好主意!但最終我通過在完成後臺任務時取消對SceneryFile的依賴來解決此問題,並將任何問題序列化到我返回的新列表中。這似乎是可靠的 – ScruffyDuck