2

Can anyone explain what I need to do to get past this error?

"Cannot convert anonymous method to type 'System.Windows.Threading.DispatcherPriority' because it is not a delegate type"

    private void Test(object sender)
    {
        base.Dispatcher.BeginInvoke(delegate
        {
                       //some code

        }, new object[0]);
    }

Thanks

user1320651
  • 808
  • 2
  • 15
  • 42
  • Have a look at http://stackoverflow.com/questions/6245744/invoking-wpf-dispatcher-with-anonymous-method and http://stackoverflow.com/questions/968709/anonymous-methods-and-delegates – Klaus78 Oct 15 '12 at 14:50

3 Answers3

2

If you're using .NET 3.5 SP1 and upwards, then you can add a reference to System.Windows.Presentation.dll and make sure you have using System.Windows.Threading; at the top of the file. It contains extension methods that are easier to use, and allow you to simply write:

base.Dispatcher.BeginInvoke(() => { /* some code */ });

If you're using .NET 3.5 without SP1 or lower, then you'll have to cast the delegate to a concrete delegate type:

base.Dispatcher.BeginInvoke((Action) delegate { /* some code */ }, new object[0]);
Allon Guralnek
  • 15,813
  • 6
  • 60
  • 93
  • Actually, the first doesn't compile using .NET 4.0 in VS 2010. Are you sure? – Thorsten Dittmar Oct 15 '12 at 15:03
  • @ThorstenDittmar: For the extension method trick, you might also need to add a `using System.Windows.Threading;` directive if you don't already have it. – Allon Guralnek Oct 15 '12 at 15:04
  • I have this included, but still the first code doesn't compile with an error like "Cannot convert lambda expression to "System.Delegate" as it is not a delegate type" (sorry, using German VS 2010 - no English message available :-)). – Thorsten Dittmar Oct 15 '12 at 15:29
  • @Thorsten: Then you didn't add a reference to *System.Windows.Presentation.dll*. The method is described [here](http://msdn.microsoft.com/en-us/library/cc647516.aspx). – Allon Guralnek Oct 15 '12 at 15:41
  • Ha! Right again :-) Works as soon as I add the reference. – Thorsten Dittmar Oct 15 '12 at 15:52
0

EDIT
I got confused with you passing new object[0] as "parameter" to BeginInvoke and didn't realize that this actually means "no parameters", as everything following the delegate is in the params collection...

I'm making an example that expects a single integer.

You want to pass parameters, so it's best to use this

private void Test(object sender)
{
    base.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action<int>)delegate(int i)
    {
                   //some code

    }, 5);
}

This creates an anonymous delegate that takes an integer, converts this to an action that takes an integer and calls the delegate with the parameter 5.

Thorsten Dittmar
  • 55,956
  • 8
  • 91
  • 139
  • This code throws a `TargetParameterCountException` (Message="Parameter count mismatch."). This is because the delegate passed to `BeginInvoke` must have parameters matching the provided parameter array, and not simply a single parameter of type `object[]`. – Allon Guralnek Oct 15 '12 at 15:03
  • Ah, I thought he's passing an array as the single parameter (`new object[0]`). I didn't realize that this means "no parameters", as it is interpreted as `params` collection. Interesting side-question: how would I pass an array object to `BeginInvoke` so I can have a delegate that expects a single `object[] array` parameter? – Thorsten Dittmar Oct 15 '12 at 15:09
  • Instead of `new object[0]` you would provide for example `new object[] { new object[5] }`. The `Action` would get the five-element array as its argument. That would work with the above code. Also, this has nothing to do with `params`, but rather how a delegate is invoked with `.DynamicInvoke(...)`. – Allon Guralnek Oct 15 '12 at 15:12
  • Usually, a new thread isn't created when using a `Dispatcher`. The whole point of a `Dispatcher` is to run code on an existing thread. – Allon Guralnek Oct 15 '12 at 15:17
  • You're right with your last comment - I'll change that. However, I disagree on the comment before that. Calling `BeginInvoke(..., new object[2])` would cause the error, as internally the array is treated as if I had called `BeginInvoke(..., null, null)`, so the delegate would have to take two nullable arguments. Calling `BeginInvoke(..., new object[0])` is equivalent to calling `BeginInvoke(...)`. Or am I totally off track here? – Thorsten Dittmar Oct 15 '12 at 15:26
  • Oh I see what you mean now. You meant to send the `new object[0]` as the single parameter for `params` but instead it was construed as ignoring the `params` syntax and manually specifying the array. That is a common pitfall of `params`. Regardless, `params` itself is not responsible for mapping array elements to parameters, that is the responsibility of .NET's reflection mechanisms that can dynamically invoke a delegate. – Allon Guralnek Oct 15 '12 at 15:38
0

Updated Answer

Cast the delegate to Action (or to Func<something> if you are returning a value).

private void Test(object sender)
{
    base.Dispatcher.BeginInvoke((Action)delegate
    {
        //some code
    }, new object[0]);
}

The first parameter of the Dispatcher.BeginInvoke method requires a System.Delegate. This is uncommon. Usually you would specify one of the Func or Action overloads. However, here it is possible to pass delegates with different signatures. Obviously anonymous delegates are not casted to System.Delegate implicitly.


UPDATE

I am working with .NET 3.5. In later Framework versions additional overloads of BeginInvoke may disturb C#'s overloading mechanism. Try

private void Test(object sender)
{
    base.Dispatcher.BeginInvoke((System.Delegate)(Action)delegate
    {
        //some code
    }, new object[0]);
}
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188