14

I want to execute this code on main thread in WPF app and getting error I can't figure out what is wrong:

private void AddLog(string logItem)
        {

            this.Dispatcher.BeginInvoke(
                delegate()
                    {
                        this.Log.Add(new KeyValuePair<string, string>(DateTime.Now.ToLongTimeString(), logItem));

                    });
        }
katit
  • 17,375
  • 35
  • 128
  • 256
  • 1
    Take a look here http://stackoverflow.com/questions/4936459/dispatcher-begininvoke-cannot-convert-lambda-to-system-delegate – MethodMan Apr 10 '13 at 20:38

2 Answers2

24

Anonymous functions (lambda expressions and anonymous methods) have to be converted to a specific delegate type, whereas Dispatcher.BeginInvoke just takes Delegate. There are two options for this...

  1. Still use the existing BeginInvoke call, but specify the delegate type. There are various approaches here, but I generally extract the anonymous function to a previous statement:

    Action action = delegate() { 
         this.Log.Add(...);
    };
    Dispatcher.BeginInvoke(action);
    
  2. Write an extension method on Dispatcher which takes Action instead of Delegate:

    public static void BeginInvokeAction(this Dispatcher dispatcher,
                                         Action action) 
    {
        Dispatcher.BeginInvoke(action);
    }
    

    Then you can call the extension method with the implicit conversion

    this.Dispatcher.BeginInvokeAction(
            delegate()
            {
                this.Log.Add(...);
            });
    

I'd also encourage you to use lambda expressions instead of anonymous methods, in general:

Dispatcher.BeginInvokeAction(() => this.Log.Add(...));

EDIT: As noted in comments, Dispatcher.BeginInvoke gained an overload in .NET 4.5 which takes an Action directly, so you don't need the extension method in that case.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I had the same problem and then found out that the in the 4.5 version of .NET the Dispatcher class got overloads (for instance: http://msdn.microsoft.com/en-us/library/hh199416(v=vs.110).aspx) that accept an Action delegate, so the code works without explicit delegate type specification. – Mark Vincze Jul 23 '14 at 09:12
4

You can also use MethodInvoker for this:

private void AddLog(string logItem)
        {
            this.Dispatcher.BeginInvoke((MethodInvoker) delegate
            {
                this.Log.Add(new KeyValuePair<string, string>(DateTime.Now.ToLongTimeString(), logItem));
            });
        }
Pinetwig
  • 673
  • 5
  • 13