CSharp/C# >> Anonymous Delegate

by Stefan Hoffmann » Thu, 28 Aug 2008 20:56:23 GMT

hi @all,

is there something like an anonymous delegate?

This is the original code:

I'd like to avoid the delegate declaration, e.g.:

Is this possible?


mfG
--> stefan <--

CSharp/C# >> Anonymous Delegate

by Barry Kelly » Thu, 28 Aug 2008 21:24:12 GMT



If you're using C# 3.0:

this.Invoke((Action) () => this.Text = text);

Action delegate type is in the System namespace in System.Core assembly.

If you're using C# 2.0:

delegate void Action(); // a single delegate type will do for all
// ...
this.Invoke((Action) delegate { this.Text = text; });

The reference to 'text' in the C# 3.0 syntax (lambda syntax) and in the
C# 2.0 anonymous delegate syntax is ok, because the parameter will be
captured and thus made available to the delegate when the control
invokes it on the UI thread.

-- Barry

--
http://barrkel.blogspot.com/

CSharp/C# >> Anonymous Delegate

by Stefan Hoffmann » Thu, 28 Aug 2008 21:30:02 GMT

hi Barry,

thanks for your answer.


mfG
--> stefan <--

CSharp/C# >> Anonymous Delegate

by Ben Voigt [C++ MVP] » Fri, 29 Aug 2008 03:52:47 GMT

> If you're using C# 2.0:

Use MethodInvoker instead of defining your own. The CLR recognizes
MethodInvoker and executes a specialized fast-path implementation of Invoke.

CSharp/C# >> Anonymous Delegate

by Peter Duniho » Fri, 29 Aug 2008 04:38:48 GMT

On Thu, 28 Aug 2008 12:52:47 -0700, Ben Voigt [C++ MVP]



Can you elaborate? I can see in Reflector that the framework (the Control
class, not the CLR) special-cases delegates of type EventHandler,
MethodInvoker, and WaitCallback. For those types, it casts directly
rather than calling Delegate.DynamicInvoke().

But do most people really care? Just what kind of performance difference
are we talking about here? Especially given all the other overhead
involved in calling Invoke() (after all, for the true cross-thread case it
involves a full context switch, which is surely at least as costly as any
of the extra work in DynamicInvoke()?).

Seems like a premature optimization to me. Is there some specific reason
to believe otherwise (especially given that the framework-defined Action
delegate type could be considered more expressive)?

Pete

CSharp/C# >> Anonymous Delegate

by Ben Voigt [C++ MVP] » Fri, 29 Aug 2008 07:08:09 GMT


Ok, didn't check whether that was MSIL or internalcall. Doesn't much
matter, does it?


Posting a message to another thread waits for the next context switch, it
doesn't insert an extra context switch.

Plus, DynamicInvoke is a very expensive operation.


The documentation ( http://msdn.microsoft.com/en-us/library/zyzhdc6b.aspx )
says:
The delegate can be an instance of EventHandler, in which case the sender
parameter will contain this control, and the event parameter will contain
EventArgs..::.Empty. The delegate can also be an instance of MethodInvoker,
or any other delegate that takes a void parameter list. A call to an
EventHandler or MethodInvoker delegate will be faster than a call to another
type of delegate.

Also "premature optimization" assumes that there's a cost to the
optimization. Here, there's effectively no cost at all.

CSharp/C# >> Anonymous Delegate

by Peter Duniho » Fri, 29 Aug 2008 08:35:40 GMT

n Thu, 28 Aug 2008 16:08:09 -0700, Ben Voigt [C++ MVP]
< XXXX@XXXXX.COM > wrote:


No, not really. I just like being precise.


I suppose that depends on how you look at it. Calling Invoke() blocks the
calling thread, which will prematurely relinquish the current timeslice.
If you've got a CPU bound thread, with the usual 50ms timeslice, but it's
calling Invoke() every 5ms, I'd say that's adding 9 context switches for
every context switch that would have happened otherwise.

I'll acknowledge that you may have some other way of looking at it in
which you come to a different conclusion. But by my reckoning, Invoke()
does in fact wind up forcing a context switch that wouldn't otherwise
happen.

Maybe you're thinking of BeginInvoke() instead? I'd agree that that
method doesn't add context switches to the execution of the code.


The whole process of invoking is a very expensive operation. That
DynamicInvoke is "very expensive" isn't necessarily important.

In particular, by my measurements it doesn't look like it's expensive
enough to cause a significant difference in performance. I ran a little
test, calling Invoke() 100,000 times in a row with a do-nothing method,
once with a type of MethodInvoker and once with a type of Action.

The timing was more sensitive to which test ran first than to the actual
type. That is, the first test always was slower, regardless of which type
was being used for the call. Changing the test so that it did a "warm-up"
first, I found more consistent results showing that 100,000 calls took
about 3.3 seconds for MethodInvoker and 4.2 seconds for Action.

If I changed the test so that the method actually did something useful --
for example, setting the Text property of a control to the formatted value
of my loop index -- the execution time dropped precipitously. Almost 40
seconds in either case, a 10x slowdown.

So, yes it's faster to call MethodInvoker, but putting that into context
it means you really don't want to be calling Invoke() _either_ way too
often, assuming the delegate is actually doing to be doing something
interesting, and in any case the overhead of the call is very tiny as
compared to the cost of whatever code might actually be executed by the
delegate (10% at the most).


Well, I can't say the documentation is wrong. My own tests prove it
correct. But that's only because the docs don't quantify how much
faster. I wouldn't call the difference significant.


Eye of the beholder. Personally, I find the newer generic delegate types
more expressive. But sure...if you don't personally see any difference
between "MethodInvoker" and "Action" semantically, the only cost involved
is that of remembering which is faster and of typing the extra
characters. Obviously neither costs is significant.

However, I still find it misleading to imply that the optimization is
worth doing. I saw no practical difference in performance, even if there
was a tiny measurable difference. No real world application is going to
find it matters which delegate type you use.

Pete

CSharp/C# >> Anonymous Delegate

by Barry Kelly » Sat, 30 Aug 2008 01:39:28 GMT


Knowing a piece of trivia is a cost :)

-- Barry

--
http://barrkel.blogspot.com/

Similar Threads

1. Anonymous Method vs. Anonymous Delegate - CSharp/C#

2. Anonymous Delegates, captured variables and ThreadStart

Hi,

I recently came to debug some old code that was causing a
StackOverflowException. The code in question makes significant use of
recursion and with large data structures it exhausted the stack. As
the code is complicated and would take significant re-testing it
wasn't practical to re-write it at present.

As a work-around until the code could be re-written, I decided to
invoke it on a new thread to which I had allocated a larger stack, and
then block the calling thread until the work was complete. The code I
wrote was like follows:

----8<----

MyResult[] results;
Exception ex;
ThreadStart ts = new ThreadStart(
  delegate
  {
    try
    {
      results = DoWork();
    }
    catch (Exception threadEx)
    {
      ex = threadEx;
    }
  }
);

Thread t = new Thread(ts, STACKSIZE);
t.Start();
t.Join();

if (ex != null)
{
  // etc...
}

foreach (MyResult result in results)
{
  // etc...
}

----8<----

This fixed the StackOverflowException and appeared to work. A short
while later it occurred to me that this approach was not thread-safe.

It's easy to look at that code and read it as if you're only using
local variables, but in fact you are using a public class member
variable in a class generated by the compiler for the anonymous
delegate. Whilst there's nothing to synchronise as such because the
main thread is blocked waiting, you *do* need a memory barrier to be
thread-safe.

To prove my theory I constructed the following test case. On my
machine, with a Release build and no debugger attached, the while loop
never exits as the hasFinished variable gets enregistered and so never
sees the update from the other thread.

----8<----

using System;
using System.Threading;

namespace ThreadObserver
{
  class Program
  {
    static void Main(string[] args)
    {
      bool hasFinished = false;

      ThreadStart ts = new ThreadStart(
        delegate
        {
          Thread.Sleep(5 * 1000);
          hasFinished = true;
        }
      );

      Thread t = new Thread(ts);
      t.Start();

      while (!hasFinished)
      {
      }

      Console.WriteLine("Finished.");
      Console.Read();
    }
  }
}

----8<----

It's actually fairly easy to fix, even still using anonymous delegates
- just make sure you capture a lock object to use when reading/writing
the return value(s). The following code always exits successfully:

----8<----

using System;
using System.Threading;

namespace ThreadObserver
{
  class Program
  {
    static void Main(string[] args)
    {
      object myLock = new object();
      bool hasFinished = false;

      ThreadStart ts = new ThreadStart(
        delegate
        {
          Thread.Sleep(5 * 1000);
          lock (myLock)
          {
            hasFinished = true;
          }
        }
      );

      Thread t = new Thread(ts);
      t.Start();

      bool fin;
      do
      {
        lock (myLock)
        {
          fin = hasFinished;
        }
      } while (!fin);

      Console.WriteLine("Finished.");
      Console.Read();
    }
  }
}

----8<----

This is probably an unusual case, but thought this would be worth
posting in case anyone else has used a similar pattern or is thinking
of doing so.

It highlighed to me just how necessary it is to keep remembering what
the compiler is and isn't doing for you when you use convenient
language features such as anonymous delegates.



Regards,

Matt

3. BeginInvoke and anonymous delegate - CSharp/C#

4. very strange effect with anonymous delegates (.net 2.0)

I have a very funny/strange effect here.

if I let the delegate do "return 
prop.GetGetMethod().Invoke(info.AudioHeader, null);"
then I get wrong results, that is, a wrong method is called and I have no 
clue why.
But if I store the MethodInfo in a local variable I works as expected.

I do not understand why this is so, shouldn't both ways be semantically 
equal?

foreach (PropertyInfo prop in typeof(Au.AuHeader).GetProperties())
{
    ColumnInfo col = ColumnInfoFromProperty(prop);

    // very strange effect: If I do not store MethodInfo here in a local 
variable,
    // but instead call prop.GetGetMethod() directly from the delegate I get 
wrong results
    MethodInfo mi = prop.GetGetMethod();

    col.SortValue = delegate(FileInformation info) { return 
mi.Invoke(info.AudioHeader, null); };

    cols.Add(col);
}


5. Unsubscribing an anonymous delegate? - CSharp/C#

6. Anonymous Delegates and Events

Once the form is activated I would like to remove the reference to the
anonymous delegate. Can I reference the delegate from within the delegate?
For example ...

form.Activated += delegate
{
     wasActivated = true;
      form.Activated -= ????
}


next time form is activeated, this shouldn't be called again.

Thoughts?



7. Memory Leak in C# 2.0 W/ Anonymous Delegates? - CSharp/C#

8. Assign an anonymous delegate to an hashtable

Hi,

Building the following code


namespace DelegateAnonymousToMap
{
    class Program
    {
       class MyClass { }

       static void Main(string[] args)
       {
          System.Collections.Hashtable hash = new 
System.Collections.Hashtable();
          hash.Add(1, delegate() { return new MyClass(); });
       }
    }
}


I get:

C:\..\Program.cs(14,10): error CS1502: The best overloaded method match 
for 'System.Collections.Hashtable.Add(object, object)' has some invalid 
arguments
C:\..\Program.cs(14,22): error CS1503: Argument '2': cannot convert from 
'anonymous method' to 'object'


How may I solve this problem using anonymous delegate?

TIA.
Marco.