Everyone's heard of multithreading, but not many people know exactly what it means, much less how to do it properly. Every Windows application, .NET or otherwise, runs in a thread, the basic component of processing. The operating system doles out resources to threads, and all execution takes place within a thread. All applications use threads, and many use only a single thread (for example, Notepad).
As its name implies, a thread is linear. Only one thing can be going on at a time in a thread because a CPU can process only one thing at a time (though it does so very quickly). This is why most applications can only do one thing at a timewhy you can't send and receive IMs at the same time.
With Windows, there's no rule that says an application can have only one thread. An application will always have a main thread (which the operating system creates when the application starts and then destroys when the application quits), but generally, the program is free to create additional threads as it needs them (assuming, of course, that there are available resources). With multiple threads, you can do multiple things at once in a single application. (Note, however, that the CPU still technically only processes one thread at a time, but at least your application thinks there are two things going on at once.)
Threading in .NET is handled by the classes in the System.Threading namespace, of which we are interested in only one: Thread. When you create an instance of the Thread class, you are creating a new thread for the operating system to handle. This new thread can go off by itself, doing the things it needs to do, without bothering about the main thread. However, because the main thread is the one controlling the application, you need a way for the new thread to report back. Otherwise, the new thread would go on forever and your application would lose control of ita rogue thread.
This process is done through callbacks. When the new thread needs to get in touch with the main thread, it raises an event, just like any other .NET Windows Forms control, which the main thread catches and deals with appropriately.
Now, imagine the IM application again. Your main thread is running the application, allowing you to type messages and send them. Meanwhile, in the background, you have another thread going that sits and listens for incoming messages. When it receives one, it notifies the main thread, which takes the message and displays it properly. The background thread then continues waiting for more messages. Simple as that! (Remember that the sending and receiving of messages is done with the TcpClient and TcpListener classes.)