[英]C#, WPF, Automatically call Dispatcher.Invoke when needed?
我有一個嵌入了Geospace地圖的程序。 地圖的事件處理在單獨的線程上處理,以使地圖保持響應(例如,單擊地圖時觸發的事件)。
我遇到的問題是當地圖觸發一個事件時,我的程序需要更新它的gui中的一些東西,並且還回調到地圖以處理在地圖上放置圖片。
我嘗試在this.Dispatcher.Invoke中包裝整個事件處理程序方法,這使我回到主UI線程。 這對於更新我的GUI非常有用,但是當我回調到地圖時,我仍然在UI線程上,這可能會導致地圖中出現一些問題。
基本上,為了使這項工作,每次我想要更改我的gui上的控件時,我將不得不運行dispatcher.invoke。 有沒有辦法我可以自動執行此操作而不在dispatcher.invoke中包裝每個調用? 我希望這一切都有道理。
下面是我正在談論的事件的一些示例代碼。
private void Map_OnMapClicked(object sender, MapClickedEventArgs e)
{
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
// Do something to update my gui
}));
Map.DoSomethingInTheMap();
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
// Do something to update my gui
}));
//etc etc etc
}
如果您需要將每個相應的操作保留在自己的同步上下文中,那么這是最好的方法。 每當更新GUI時,您都需要使用Dispatcher進行調用。
以下是一些使這更容易的建議:
嘗試批量處理GUI操作。 除了需要更少的代碼(通過較少的調用調用),您將獲得更好的性能。 每個Dispatcher.Invoke調用都會帶來相當大的開銷,因為它會將消息發布到Dispatcher的消息隊列中,必須對其進行處理。
考慮使用Dispatcher.BeginInvoke來避免阻塞,除非你真的需要等待。
如果您可以使用.NET 4中的任務並行庫(或Rx Framework中的backport到3.5sp1),您可能需要考慮重新處理它以使用同步到GUI線程的Task實例 。 通過使用FromCurrentSynchronizationContext創建TaskScheduler,您可以安排在GUI上運行的任務比Dispatcher Invoke調用更容易。 這也可以讓您對批處理有一些控制權,因為您可以非常輕松地安排它們,並根據需要阻止/等待。
你可以使用像PostSharp這樣的東西,或者嘗試將你的UI更新壓縮到單個方法調用,你可以調用一次並做很多事情。 甚至是這樣的模式(它是Winforms,但想法是一樣的):
private void UpdateToolStripItemText(ToolStripItem toolStripItem, string text)
{
if (InvokeRequired)
{
Invoke(new UpdateToolStripItemTextDelegate(UpdateToolStripItemText), new object[] { toolStripItem, text });
}
else
{
if (text != null)
{
toolStripItem.Text = text;
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.