Strange behaviour of Console.ReadKey() with multithreading
This is a race condition. Here is what's happening when the first Console.WriteLine is not there:
- Task is created, but not run
- Console.ReadKey executes, takes a lock on Console.InternalSyncObject, and blocks waiting for input
- The Task's Console.WriteLine calls Console.Out, which calls Console.InitializeStdOutError for first-time initialization to set up the console streams
- Console.InitializeStdOutError attempts to lock on Console.InternalSyncObject, but Console.ReadKey already has it, so it blocks
- The user presses a key and Console.ReadKey returns, releasing the lock
- The call to Console.WriteLine is unblocked and finishes executing
- The process exits, because there is nothing in Main after the ReadKey call
- The remaining code in the Task does not get a chance to run
The reason it behaves differently when the Console.WriteLine is left in there is because the call to Console.InitializeStdOutError is not happening in parallel with Console.ReadKey.
So the short answer is: yes you are abusing Console. You could either initialize the console yourself (by dereferencing Console.Out), or you would wait on an event after starting the Task, but before ReadKey, and then have the Task signal the event after calling Console.WriteLine the first time.
Sometimes thread does not start
This is an ideal case of race condition. Here you are creating a thread and subsequently starting it. But keep in mind, there is a delay for the thread to actually run once you call start
method on it. Possibly, this delay give chance for your Console.ReadKey
method to get into flow of execution and wait for user input. At this stage, Console.ReadKey
method block your console through taking a lock on Console.InternalSyncObject
, and blocks waiting for input. This case other execution path to block until we key in. Once you press the Key, which indirectly release the lock on Console.InternalSyncObject
and allow the thread continue its execution. I presume, this is what happening in your case.
Though it is not to replace what you are trying to achieve, you can see the thread executing when you replace Console.RedKey
to Console.ReadLine()
.
multithreading behavior strange C#!
See Eric Lippert's excellent blog post on this issue.
This is being caused by access to a "modified closure".
Change your loop's body to this:
for (int i = 1; i<=3; i++)
{
int j = i; // Prevent use of modified closure.
Thread thread = new Thread(() => testThread("" + j + "__"));
thread.Start();
}
(Note that for a foreach
loop, this was fixed in .Net 4.5, but it was NOT fixed for a for
loop.)
Related Topics
ASP.NET Web Application Message Box
Efficient Cartesian Product Algorithm
The Property 'Id' Is Part of the Object's Key Information and Cannot Be Modified
Datagridview Using Sortablebindinglist
How Can Xml Documentation for Web API Include Documentation from Beyond the Main Project
Most Efficient Method of Self Referencing Tree Using Entity Framework
This Row Already Belongs to Another Table Error When Trying to Add Rows
How to Restrict Access to Nested Class Member to Enclosing Class
Can the Oracle Managed Driver Use Async/Await Properly
How to Turn Off Impersonation Just in a Couple Instances
How to Access Ssis Package Variables Inside Script Component
C# Regular Expressions, String Between Single Quotes
Get the Final Generated HTML Source Using C# or Vb.Net
.Net Core Identity Server 4 Authentication VS Identity Authentication