こんにちは、プロデューサーとコンシューマーのパターンがあります。WPF UI は、パケットをリッスンしてタスクをキューに入れている、長時間実行されるワーカー スレッドの補助的なものです。実際には、すべてのメッセージがキューから取り出されてから、UI コンシューマーが処理します。
私が抱えている問題は、すべての WPF GUI コンポーネントを担当する UIcontroller クラスがあることです。デキューされた各タスクを表示する新しいウィンドウを開き、参照されたウィンドウのスレッドセーフなコレクションを保持します。
Despatcher.BeginInvoke で通知します。そこに驚きはありません。
私が抱えている問題は、UIController クラスが構成された数のウィンドウを正常に開いた場合に、ワーカー スレッドを一時停止/文字通り停止したいということです。開いているウィンドウの数には制限があります。開いているウィンドウの数が範囲内に戻ったら、キューの処理を再開します。このクラスでウィンドウ コレクションを保持し、参照によって更新される呼び出しを介して UI に渡そうとしましたが、Begin Invoke は非同期であり、ワーカー スレッドのループでカウントが時間内に更新されません。
UIcontrollerクラスで開いているウィンドウの数をテストし、そこからタスクを無視して再キューイングすることもできました-基本的に何もしません。しかし、私はよりクリーンなソリューションが欲しいです。
ある種のクリーンなコールバックを行うことはできますか?
public void Work()
{
while (true)
{
Log.Instance.Info("****In worker THREAD " + _worker.Name);
while (_controller.IncomingMessages.Count > 0 && [--test for no of windows open on GU thread somehow - I did try holding a reference to the collection in this class--])
{
try
{
Log.Instance.Info("****In Notification worker THREAD and messages to process " + _worker.Name);
Messages.AlertMessage task = null;
lock (_locker)
{
if (_controller.IncomingMessages.Count > 0 && ToasterPopUps.Count < 5)
{
task = _controller.IncomingMessages.Dequeue();
if (task == null)
{
return;
}
}
if (task != null)
{
Log.Instance.Info("Dequeing: " + task + " " + task.ID + " from Notification thread");
_UIthread.BeginInvoke(DispatcherPriority.Background, new JoinUIThread(DespatchUIThread), task, _UIthread);
}
}
}
catch (Exception err)
{
Log.Instance.Critical(string.Format("Unexpected Error in PollPopUp Thread Queue {0} ", err));
}
}
Log.Instance.Info("No more Notification tasks - wait for a signal");
_wh.WaitOne();
}
}
public void DespatchUIThread(Messages.AlertMessage task, System.Windows.Threading.Dispatcher dispatcherThread)
{
try
{
_controller.CreateWindow(task, dispatcherThread);
}
catch (Exception err)
{
Log.Instance.Critical("Critical error " + err);
}
}