No way should it be "multiple exes". Those would be different processes. Processes are well isolated; there are given separate address spaces (if one process tries to use the same pointer, it points to a different physical memory address, this is the isolation supported by hardware, paged memory). Process are primarily designed for isolation, not for collaboration which would required such a bottleneck as IPC.
[EDIT]
More exactly, in some relatively rare cases, using "multiple exes" could be an acceptable option. Reluctantly, I used such techniques myself. For example, to run some command-line OS utility which is hard or impossible to write from scratch or through any accessible API. But "multiple exes" technique is not suitable as a regular/mainstream approach to modularization.
(Credit to the comment by C Pallini below.)
[END EDIT]
Of course, you can, and, in many cases, you should use multiple threads. They are not isolated and should communicate using thread synchronization primitives.
Now, how about separate forms? It depends on the application. For majority of applications, even multiple forms is not the best idea. Majority of best application uses one main form, and, inside this main form, there are controls (say, panels) which play the same role as your separate forms. Look at the docked UI of Visual Studio, for a typical example. Much simpler UI is based on the TabControl
class (there are different classes for Forms and for WPF).
Above, I didn't mean modal (pop-up) forms. Of course, they are separate be definition and don't count. But, in a well-styled single-form application, even the number of those modal forms should be limited. Most operations should be "non-linear" (I borrowed this term from the field of video editors), which means that the user can control almost any aspect of the application at any moment, not in any predefined order (as in "wizards"). Modal forms prevent modifying any states on other forms until the modal form is closed, so use them sparingly.
—SA
Updated 29-Oct-14 10:34am
v5