Is Debug.WriteLine() thread safe?
According to this, it is thread safe. But, in my multithreaded program I am getting some strange output.
For example:
// these statements are found throughout the program
Debug.WriteLine("Polled database. {0} batch items retrieved.", items.Count());
Debug.WriteLine("Queued batch item: {0}", bm.BatchName);
Debug.WriteLine("Discarded batch item: {0} already queued.", bm.BatchName);
Debug.WriteLine("Creating task for batch item: {0}", bm.BatchName);
Debug.WriteLine("Removed batch item from processing items collection: {0}", bm.BatchName);
Debug.WriteLine("Could not remove batch item from processing items collection: {0}", bm.BatchName);
Debug.WriteLine("Begin Processing: {0}", bm.BatchName);
Debug.WriteLine("End Processing: {0}", bm.BatchName);
"Polled database. 0 batch items retrieved."
"Polled database. 0 batch items retrieved."
"Polled database. 0 batch items retrieved."
"Polled database. 0 batch items retrieved."
"Polled database. 1 batch items retrieved."
"ronnie's batch: Queued batch item: {0}"
"ronnie's batch: Creating task for batch item: {0}"
"Begin Processing: ronnie's batch"
"Polled database. 1 batch items retrieved."
"ronnie's batch: Discarded batch item: {0} already queued."
"End Processing: ronnie's batch"
"ronnie's batch: Removed batch item from processing items collection: {0}"
"Polled database. 0 batch items retrieved."
You can see that things start going off the rails with ronnie's batch: Queued batch item: {0}
If I use string.Format() first, I don't have the problem. What is going on?
Answers. Yes, they are. Although TextWriter methods are not, Console. Out uses a SyncTextWriter which is thread-safe.
Definition. Writes information about the debug to the trace listeners in the Listeners collection.
Debug. WriteLine writes to the debug output. You can see it in your debugger and save it from there.
The problem is that you're not calling the overload you think you are. You're calling Debug.WriteLine(string, string)
which uses the first parameter as the message and the second as a category, not a format argument.
The simplest way to fix this is to cast your argument to object
to force it to use the Debug.WriteLine(string, params object[])
overload:
Debug.WriteLine("Queued batch item: {0}", (object) bm.BatchName);
A slightly longer-winded approach, but one which is perhaps more object, is to explicitly create the array:
Debug.WriteLine("Queued batch item: {0}", new object[] { bm.BatchName });
Or (just to keep supplying options :) call string.Format
explicitly to call the Debug.WriteLine(string)
overload:
Debug.WriteLine(string.Format("Queued batch item: {0}", bm.BatchName));
or when you're just including the argument directly at the end:
Debug.WriteLine("Queued batch item: " + bm.BatchName);
Alternatively, you might want to create your own convenience method which doesn't have the extra, unhelpful (in your case) overload.
I know this is an old thread and it's not super relevant to the question, but with newer versions of .NET you can also use the interpolation:
Debug.WriteLine($"Queued batch item: {bm.BatchName}");
Also if you end up here, yes it is threadsafe. This is not, which I found out the hard way:
Console.WriteLine($"Queued batch item: {bm.BatchName}");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With