Thread B isn't listening to the event. It may have been the thread that added the event handler, but that thread isn't what's listening.
You can't just go at any time and tell a currently running thread to go and execute some other method instead of what it's doing. When you start a new thread you give it a place to start, and it just executes code there until it's done, and that's all.
When you run code on the UI thread you can do it because the UI thread has a message loop. It has a queue of delegates, and the code that the thread is running looks something like this:
while(!applicationStopped)
{
Action nextAction = queue.Dequeue();
nextAction();
}
While there is a bit more to it (error handling, for example) that's the general idea. To "run code in the UI thread" you just add a delegate to the queue, and it will eventually be run in the UI thread.
You'll need some similar mechanism if you want to run code in your thread B. You'll need to have some sort of delegate, queue, or other medium of providing a delegate that it should execute, and that thread needs to be checking that location for delegates that it's supposed to run. In the general case, this is often not feasible, unless this other thread is similar to a UI thread in that it does nothing but execute delegates it's given from other locations.