Why the Overhead for Multi Threaded Access to WPF UI controls?

后端 未结 3 809
灰色年华
灰色年华 2021-01-16 08:32

Have I missed something with WPF (and Windows Forms before it) in regards to the need to write a lot of repetitive code when developing multi-threaded applications. Every UI

相关标签:
3条回答
  • 2021-01-16 08:56

    Don't forget lambdas:

    int myParam = 5;
    
    Dispatcher.BeginInvoke((Action)(() => SomeMethod(myParam)));
    

    There is also a hidden intellisense method on the dispatcher:

    if(Dispatcher.CheckAccess())
        DoSomething();
    
    0 讨论(0)
  • 2021-01-16 09:07

    Well you can certainly make it simpler than that. For one thing you don't need all your own separate delegate types - you can use the built-in Func<...> and Action<...> delegates if you're using .NET 3.5, and if you're not you can declare them yourself and then use them generically.

    The other thing you might consider is writing a helper method (as an extension method, if you're using C# 3) and then use anonymous methods (or lambda expressions):

    internal static void SetElementIsEnabled(UIElement element, bool isEnabled)
    {
        InvokeIfNecessary(element, delegate
        {
            element.IsEnabled = isEnabled;
        });
    }
    

    The helper method would be:

    public static void InvokeIfNecessary(UIElement element, MethodInvoker action)
    {
        if (element.Dispatcher.Thread != Thread.CurrentThread)
        {
            element.Dispatcher.Invoke(DispatcherPriority.Normal, action);
        }
        else
        {
            action();
        }
    }
    

    (You should probably also include a BeginInvoke equivalent. I generally prefer BeginInvoke unless I need the rendezvous.)

    0 讨论(0)
  • 2021-01-16 09:12

    Simply put, for performance reasons. Why should every GUI app have to take on the performance implications of marshalling code when only those that are multi-threaded require it?

    Further, you can design your app to have less cross thread chatter, so that less invoking is necessary.

    Also, your code is not particularly efficient. a better approach is:

    if ( InvokeRequired ) {
        Invoke(new MethodInvoker(this.Function));
    } else {
        // do code
    }
    

    EDIT: I guess my code is more for Windows Forms while yours is for WPF, but the purpose is the same. Windows requires that all control updates occur on the thread that created the control due to thread local storage issues. And this is just not something that should be there for all uses.

    0 讨论(0)
提交回复
热议问题