BackgroundWorker と DispatcherTimer に関連する SO の質問をたくさん読み、メイン スレッド以外のスレッドでは UI コンポーネントにアクセスできないことを理解しました。
だから私は 1/2 秒ごとに刻む DispatcherTimer を持っています。ご想像のとおり、ビュー モデル クラスと、直接操作が必要なすべての UI 要素を更新でき、UI は非常に応答性が高くなります。ただし、実行に約 3 秒かかる UI の値に基づいて計算する必要があります。
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 のリストを評価すると、次のエラーが発生します: base {System.SystemException} = {"別のスレッドが所有しているため、呼び出しスレッドはこのオブジェクトにアクセスできません。"}
DrawUIMap メソッドに入って MyClass.MapGeo ジオメトリ リストにアクセスしようとするまで、実際にはエラーは表示されません。この時点で、UI にアクセスできる DispatcherTimer スレッドに戻ります。
私の知る限り、UI コンポーネントにいつどこでアクセスするかについては、すべて正しく行っています。私はどこかでひどく間違ったことをしたと思いますが。
**編集:これは計算を行うコードの一部です
public static List<PathGeometry> BuildMap(List<PathGeometry> _geoList)
{
...
List<PathGeometry> retGeoList = new List<PathGeometry>();
retGeoList.Add(geoPath1);
retGeoList.Add(geoPath2);
...
return retGeoList;
}