I'm currently working on a multithread project involving several time consuming tasks running in parallel.
Every task is logging in the same file, and I need to keep it tidy (with the right order), so I found a way to log "task by task":
- When a task must write to the log file, instead I write my logs in a Dictionary :
_logList[id].Add(message)
- This Dictionary has Key = ThreadID, Value = logs of the worker with this ID (list of string)
- The ThreadID comes from
Thread.CurrentThread.ManagedThreadId
Here is how I launch my BackgroundWorkers:
foreach (MyTask task in List<MyTask> tasks)
{
BackgroundWorker bg = new BackgroundWorker();
bg.DoWork += bgworker_DoWork;
bg.RunWorkerCompleted += bgworker_RunWorkerCompleted;
List<object> arguments = new List<object>() { task, args1 };
bg.RunWorkerAsync(arguments);
}
The bgworker_DoWork delegate is the time consuming tasks, writing logs.
Then, when a task is over, the BackgroundWorker runs the delegate bgworker_RunWorkerCompleted, which basically ends the task and writes the corresponding log, in the right order:
Log.FlushWrite((int)result[2]); -- result[2] contains the threadId to flush
And FlushWrite only writes to the log file the list of logs of the threadId:
WriteMessageToFile(_logList[id]);
Most the time, this works. But sometimes, I see a weird behavior:
- Several tasks are using the same ThreadID
- When the first task N of the ThreadID X has ended, it calls the RunWorkerCompleted delegate, and flushes its logs + only a part of the next task N+1 of the ThreadID X (because the task has not ended yet)
- When the task N+1 really ends, it flushes the remaining logs to write, but the log file is a mess because it is not tidy!
I know a managed thread id might be recycled and reused, but imo the only way for this situation to happen is that the thread is already reused (new call to DoWork
) when the BackgroundWorker running has not yet called the RunWorkerCompleted
Am I right? Is there something I did not understand of this situation?
Maybe using a ManagedThreadId as a key of a Dictionary is a bad practice in that case?
Thanks for your help :)