I can see five options available:
1. Thread.Join
As with Mitch's answer. But this will block your UI thread, however you get a Timeout built in for you.
2. Use a WaitHandle
ManualResetEvent is a WaitHandle as jrista suggested.
One thing to note is if you want to wait for multiple threads: WaitHandle.WaitAll() won't work by default, as it needs an MTA thread. You can get around this by marking your Main() method with MTAThread - however this blocks your message pump and isn't recommended from what I've read.
3. Fire an event
See this page by Jon Skeet about events and multi-threading. It's possible that an event can become unsubcribed between the if and the EventName(this,EventArgs.Empty) - it's happened to me before.
(Hopefully these compile, I haven't tried)
public class Form1 : Form
{
    int _count;
    void ButtonClick(object sender, EventArgs e)
    {
        ThreadWorker worker = new ThreadWorker();
        worker.ThreadDone += HandleThreadDone;
        Thread thread1 = new Thread(worker.Run);
        thread1.Start();
        _count = 1;
    }
    void HandleThreadDone(object sender, EventArgs e)
    {
        // You should get the idea this is just an example
        if (_count == 1)
        {
            ThreadWorker worker = new ThreadWorker();
            worker.ThreadDone += HandleThreadDone;
            Thread thread2 = new Thread(worker.Run);
            thread2.Start();
            _count++;
        }
    }
    class ThreadWorker
    {
        public event EventHandler ThreadDone;
        public void Run()
        {
            // Do a task
            if (ThreadDone != null)
                ThreadDone(this, EventArgs.Empty);
        }
    }
}
4. Use a delegate
public class Form1 : Form
{
    int _count;
    void ButtonClick(object sender, EventArgs e)
    {
        ThreadWorker worker = new ThreadWorker();
        Thread thread1 = new Thread(worker.Run);
        thread1.Start(HandleThreadDone);
        _count = 1;
    }
    void HandleThreadDone()
    {
        // As before - just a simple example
        if (_count == 1)
        {
            ThreadWorker worker = new ThreadWorker();
            Thread thread2 = new Thread(worker.Run);
            thread2.Start(HandleThreadDone);
            _count++;
        }
    }
    class ThreadWorker
    {
        // Switch to your favourite Action<T> or Func<T>
        public void Run(object state)
        {
            // Do a task
            Action completeAction = (Action)state;
            completeAction.Invoke();
        }
    }
}
If you do use the _count method, it might be an idea (to be safe) to increment it using
Interlocked.Increment(ref _count)
I'd be interested to know the difference between using delegates and events for thread notification, the only difference I know are events are called synchronously.
5. Do it asynchronously instead
The answer to this question has a very clear description of your options with this method.
Delegate/Events on the wrong thread
The event/delegate way of doing things will mean your event handler method is on thread1/thread2 not the main UI thread, so you will need to switch back right at the top of the HandleThreadDone methods:
// Delegate example
if (InvokeRequired)
{
    Invoke(new Action(HandleThreadDone));
    return;
}