簡體   English   中英

C#,WPF,需要時自動調用Dispatcher.Invoke?

[英]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進行調用。

以下是一些使這更容易的建議:

  1. 嘗試批量處理GUI操作。 除了需要更少的代碼(通過較少的調用調用),您將獲得更好的性能。 每個Dispatcher.Invoke調用都會帶來相當大的開銷,因為它會將消息發布到Dispatcher的消息隊列中,必須對其進行處理。

  2. 考慮使用Dispatcher.BeginInvoke來避免阻塞,除非你真的需要等待。

  3. 如果您可以使用.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM