1

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;
}
4

1 に答える 1

0

そのオブジェクトは、それを作成した ThreadPool スレッドによって所有されます。

を呼び出すとFreeze()、他のスレッドで使用できるようになるはずです。

于 2013-10-09T16:21:01.010 に答える