Question 1: For my second method, CommonFunction2, I use a new static lock, i.e. LockObjCommonFunction2 in this example, or I can reuse the same LockObj lock object defined at the beginning of the function.
If you want to synchronize these two methods, you need to use the same lock for them. For example, if thread1 gets access to your method 1, and thread2 gets access to your method2, and you want them to not be able to access the internal ones at the same time, use the same lock . But if you just want to restrict simultaneous access only to either method 1 or 2, use different locks .
Question 2: Is there anything that can lead to problems, or can I improve the code to be a safe thread.
Always remember that shared resources (for example, static variables, files) are not thread safe, since all threads are easily accessible to them, so you need to use any synchronization (through locks, signals, mutexes, etc.).
Quesiton 3: Could there be any problems when passing a generic class instead of struct .. in this example SendMailParameters (which I use when completing all the parameters, instead of having multiple parameters for the SendMail function)?
As long as you apply the correct synchronization, it will be thread safe. For structures, see this as a reference.
The bottom part is that you need to apply the correct synchronization operations to everything that is in shared memory. Also, you should always consider the area in which you create the thread, and the state of the variables used by each method. Do they change state or simply depend on the internal state of the variable? Does this thread always create an object, although it is static / shared? If so, then it should be thread safe. Otherwise, if it just reuses a specific share, then you must apply proper synchronization. And, more importantly, even without a common resource , deadlocks can still occur, so remember the basic rules in C # to avoid deadlocks . PS thanks to Euphoric for publishing an article by Eric Lippert.
But be careful with your syncs. To the extent possible, limit their scope only where the total resource changes. Because it can lead to uncomfortable bottlenecks for your application, where performance will be severely affected.
static readonly object _lock = new object(); static SomeClass sc = new SomeClass(); static void workerMethod() {