我已經通讀了許多與BackgroundWorker和DispatcherTimer相關的SO問題,並且瞭解到您無法訪問主線程以外的任何線程上的UI組件。BackgroundWorker e.Result結果在調用線程無法訪問錯誤
所以我有每1/2秒滴答的DispatcherTimer。正如你所期望的,我可以更新視圖模型類和任何需要直接操作的UI元素,並且UI非常靈敏。不過,我有一個計算是基於UI上需要運行大約3秒的值來完成的。
我試着在DispatcherTimer線程中進行調用,並鎖定/阻止UI直到完成。目前我在DispatcherTimer中檢查,然後觸發BackgroundWorker線程關閉並執行計算。我使用e.Arguments將我需要的數據傳遞給我的3秒計算過程,並將e.Result傳遞給我返回的完成數據。
我檢查了結果,沒有產生錯誤。但是,當我將e.Result重新放入我的課程時,e.Result無法正確評估。當我來使用類屬性時,我基本上得到了「調用線程無法訪問錯誤」。
...
timerBackgroundLoop = new DispatcherTimer(DispatcherPriority.Background);
timerBackgroundLoop.Interval = TimeSpan.FromMilliseconds(500);
timerBackgroundLoop.Tick += new EventHandler(Timer_Tick);
timerBackgroundLoop.Start();
...
private void Timer_Tick(object sender, EventArgs e)
{
if (MyClass.NeedToRebuildBuildMap)
{
MyClass.NeedToRebuildBuildMap = false; //stop next timer tick from getting here
threadDrawMap = new BackgroundWorker();
threadDrawMap.WorkerReportsProgress = false;
threadDrawMap.WorkerSupportsCancellation = false;
threadDrawMap.DoWork += new DoWorkEventHandler(threadDrawMap_DoWork);
threadDrawMap.RunWorkerCompleted += new RunWorkerCompletedEventHandler(threadDrawMap_Completed);
threadDrawMap.RunWorkerAsync(myClass.MapData);
}
...
}
private void threadDrawMap_DoWork(object sender, DoWorkEventArgs e)
{
MyClass.MapData _mapData = (MyClass.MapData)e.Argument;
e.Result = BuildMap(_mapData);
}
private void threadDrawMap_Completed(object sender, RunWorkerCompletedEventArgs e)
{
MyClass.MapGeo = (List<PathGeometry>)e.Result;
DrawUIMap(MyClass.MapGeo); //draws the map on the UI into a grid
}
當我設置斷點在「threadDrawMap_Completed」和評估的PathGeometry的名單我得到這個錯誤:{基地System.SystemException} = {「,因爲不同的線程擁有它調用線程不能訪問該對象。 「}
直到當我在DrawUIMap方法中時,我才真正看到錯誤,並嘗試訪問MyClass.MapGeo幾何列表。在這一點上我回到了DispatcherTimer線程,它可以訪問UI。
據我所知,我已經做了一切正確的地方,當我訪問UI組件。儘管我認爲我在某個地方做了一些可怕的錯誤。
**編輯: 這是做的calulation
public static List<PathGeometry> BuildMap(List<PathGeometry> _geoList)
{
...
List<PathGeometry> retGeoList = new List<PathGeometry>();
retGeoList.Add(geoPath1);
retGeoList.Add(geoPath2);
...
return retGeoList;
}
你在哪裏重置'MyClass.NeedToRebuildBuildMap',我不確定,但在'timer'中使用一個標誌來防止下一個'BackgroundWoker'運行可能不是最好的選擇?可能有一個機會,國旗重置,並在它被設置爲「假」,兩個「計時器滴答作響」.. – Bolu
對不起剛剛看到您的評論。在這種情況下,答案是否定的,我仔細檢查了它只會被稱爲一次,因此移動了布爾旗。實際上,我在代碼的其他地方根據菜單項單擊設置了標誌,只要用戶基本上要求MapRedraw,我就隱藏它並顯示繁忙的指示符,直到地圖重新繪製。它比我在這裏實際聲音更優雅;-) – MikeyTT