Process.Start() hangs when running on a background thread

前端 未结 1 2052
隐瞒了意图╮
隐瞒了意图╮ 2020-12-11 08:15

I\'ve been troubleshooting all day. After doing some research and a lot of trial and error, it seems I\'ve been able to narrow down the issue to the fact that my call to

相关标签:
1条回答
  • 2020-12-11 09:05

    There are a lot of duplicate questions about this problem, none that exactly fits your case. You can see the problem by using the debugger's Debug + Windows + Threads window. Locate the timer thread and double-click it. Look at the Call Stack window to see:

    mscorlib.dll!System.Console.InputEncoding.get() + 0x66 bytes    
    System.dll!System.Diagnostics.Process.StartWithCreateProcess(System.Diagnostics.ProcessStartInfo startInfo) + 0x7f5 bytes   
    System.dll!System.Diagnostics.Process.Start() + 0x88 bytes  
    ConsoleApplication70.exe!Program.RunProcess() Line 43 + 0xa bytes   C#
    ConsoleApplication70.exe!Program.OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) Line 28 + 0x5 bytes    C#
        // etc...
    

    The thread is deadlocked on the Console.InputEncoding property getter. Which is used by the Process class to figure out what encoding needs to be used to translate the redirected output of the process into strings.

    This is specific to .NET 4.5, it will also affect apps that target 4.0 on a machine that has 4.5 installed since it is not a side-by-side version of .NET. The deadlock is caused by the Console.ReadKey() method call in your main thread. Which now acquires a lock that prevents other threads from messing with the console. This has been a fairly global change across Microsoft software, the CRT that is used in C/C++ apps created by VS2012 also added this lock. The exact reason isn't that clear to me, but surely has to do something with console output not getting intermingled with console input while your program is asking for input. Exactly why the InputEncoding property needs to take that lock as well is, well, a bit hard to explain but fits the pattern of serializing access to console input. This of course comes as a big surprise to many programmers, especially the ones that write little test apps that test threaded code, like you did. Bit of a setback to TDD.

    The workaround is a bit unpleasant, TDD wise, you do have to stop using Console.ReadKey() to avoid the deadlock. Real programs would use the WaitOne() method of an AutoResetEvent to know that the worker thread finished executing. Or CountDownEvent.Wait(), more in keeping with trying out code a couple of times. Etcetera.


    UPDATE: this deadlock scenario was resolved in a service update for .NET 4.5. Enable Windows Update on your machine to get it.

    0 讨论(0)
提交回复
热议问题