You've got a race condition, in that the work could finish before you register for the event. To avoid the race condition, change the order of the code so you register for the event before starting the work, then it will always be raised, no matter how fast it finishes:
static void Main(string[] args) { Worker worker = new Worker(); worker.WorkCompleted += PostProcess; worker.DoWork(); }
Edit:
OK the question has been modified, so it looks like what you're really asking is how to wait for PostProcess to finish executing. There are a couple of ways to do this, but you'll have to add some more code.
The easiest way is, because events always execute on the same thread as they are raised, is to call Thread.Join on the thread the Worker class creates, e.g. assuming the thread is exposed as a property:
worker.Thread.Join();
(Although to be honest I'd probably keep the Thread private and expose a method called something like WaitForCompletion on the Worker class that calls it).
Alternative methods are:
Have a WaitHandle, probably a ManualResetEvent, in the Worker class which is Set when it completes all its work, and call WaitOne on it.
Have a volatile bool complete field in the Worker class and loop while waiting for it to be set to true, using Thread.Sleep in the loop body (this probably isn't a good solution, but it is feasible).
There are probably other options too, but that's the common ones.