Unlike in C/C++, the main() is not quite the entirety of your application. So even surrounding all the code in main() with a try/catch block will not catch all exceptions generated by that code.
However, you can attach a function to handle unhandled exceptions thrown by the entire application by listening to the Application.ThreadException event, which will help you catch exceptions from any thread in the application, whether it was created by your code or not.
For example, your code may call upon the code in an external, unmanaged DLL. That code might execute threads of its own, which might asynchronously fail, causing an exception to be thrown. That exception belongs to the process that is your application, but not to any of your code. And if uncaught, will cause your program to terminate unexpectedly.