Hi,
a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.
I don't see anything particularly thread safe about your code, are you
talking about checking for null that makes this thread safe? It is safe for
a single thread but once you have multiple threads the really only safe way
is to make sure you have locks in place around adding/removing delegates to
your event and the invocation of that event i.e. the following is an example
of how two threads accessing the same event can cause a null reference
exception:
using System.Threading;
namespace CSharpConsole
{
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
t.Run();
}
}
class TestClass
{
private delegate void MyEventHandler();
private event MyEventHandler MyEvent;
public TestClass()
{
}
public void Run()
{
Thread threadA = new Thread(new ThreadStart(ThreadADoSomething));
//Add listener to the event
MyEvent += new MyEventHandler(DoSomething);
if (MyEvent != null)
{
//got in here, let the other thread run and wait until it
//completes
threadA.Start();
threadA.Join();
//whoops now this is null
MyEvent();
}
}
void ThreadADoSomething()
{
//removes the only listener
MyEvent -= new MyEventHandler(DoSomething);
}
void DoSomething()
{
}
}
}
b) Events are basically delegates, System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than that
its a pretty vanilla type.
There is a little bit more to this type, hence your posting :-) If you look
at the documentation for the delegate type you will see: "Delegates are
immutable; once created, the invocation list of a delegate does not change."
Hence the reason why when you assign you event (which is really just
syntactic sugar around delgates) to your other delegate type really you have
just made a new copy of that delegate. The contents of the
multicastdelegates invocation list inside the temp variable will therefore
not change when you update the other multicastdelegate through the SomeEvent
enty point.
The code in my original post draws the understanding reader to the
conclusion that this particular reference type is not obeying standard
reference type semantics. I thought it was pretty self-explanatory.
Why not just ask the question you want to ask :-)
--
http://www.markdawson.org
Posted from Windows Vista RC1
"CuriousGeorge" wrote:
Because no nulls are referenced?
Hmmm. OK.
a) "Code like this" is the preferred way to raise events in a thread safe
manor - you should be doing it yourself.
b) Events are basically delegates, System.Delegate is a reference type,
there's nothing special about it, it overloads += and -= but other than that
its a pretty vanilla type.
As we know and event with no subscribers is actually a null-reference hence
the check for nullility before invoking the subscribed handlers.
If you in-line the delegate call in my original post you get something like
the following (compiled in Outlook Express)
public void RaiseEvent(Callback callback)
{
EventHandler temp = SomeEvent;
SomeEvent -= theOnlyRegisteredEventHandler
//SomeEvent is now null
if (temp != null)
{
temp(this, EventArgs.Empty);
}
}
The code in my original post draws the understanding reader to the
conclusion that this particular reference type is not obeying standard
reference type semantics. I thought it was pretty self-explanatory.
"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:12*************@corp.supernews.com...
"CuriousGeorge" <***@***.comwrote in message
news:Ot****************@TK2MSFTNGP03.phx.gbl...
Can someone explain why this code DOES NOT raise a null reference
exception?
Because no nulls are referenced?
If you have reason to believe that a null reference exception should
occur, then the least you could do is explain in your post:
a) why it is you want to execute code like this, and
b) why and where it is that you think a null reference exception would
occur
Pete