You have 3 options:
Log file - good option which I actually prefer to use because I can easily deal with entries and look through it. I even make directories for the log files with the following format AppName\YYYY\MM\DD\yourfile.log so that I can see how things looked on a specific day (Have years of logging in some cases). Threading is not an issue. You can make it thread safe. This is a pretty safe method because you would almost always have access to write to disk unless your disk is full, which one of the other options should be able to handle.
Database - also good because you can query it easily. It has a large chance of failure and shouldn't be used for primary logging in my opinion. If you DB goes down is experiencing issues which cause the exception, where would you store it? Your DB could be lagging and getting timeouts etc. It can also impact your DB performance depending on how much your logging.
System event log - this goes great with 1 or 2 or both. The event log will almost always be available and this is what Windows uses (assuming a windows server) so it is very safe. You can also make app specific exceptions so you can filter out all the Windows specific stuff that you don't want to worry about. It does however only store a specific amount so your history can be short depending on how much is getting thrown in there so you might want to have a way of exporting this data on a schedule.
Most of my apps use a combination of 1 and 2. We rolled our own logging and it has worked well for us but there are some great libraries out there to help with this. We also have an in house built tool to monitor our server event logs for our specific items and notify the correct people based on specific criteria when possible. It is setup as a pull process from another server so that even when the server has issues where it maybe can't send out a notification, the monitoring server should be able to eventually get the data out and perform the correct notification.
The key, depending on how important logging is to you and your application, is redundancy. If you go the DB route, have a backup. If you go the file route, have a backup. In most cases logging can fail in specific cases so it is important to have more than one way to store the information you will need. It has saved me a ton of time figuring out issues when one of the logging methods failed for whatever reason.