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.