You can download the sample here: https://www.mesta-automation.com/Downloads/multithread.rar
With WPF it’s almost a must to use multiple threads to keep the User Interface responsive, and debugging them can be a problem when they are complex.
Usually i debug the background threads with the Console, while keeping the Main Window visible, like in the figure:
To activate the Console with WPF application you can use 2 ways (as said here):
- Right click on the project, “Properties”, “Application” tab, change “Output Type” to “Console Application”, and then it will also have a console.
- Using this class (i prefere this one):
[SuppressUnmanagedCodeSecurity] public static class ConsoleManager { private const string Kernel32_DllName = "kernel32.dll"; [DllImport(Kernel32_DllName)] private static extern bool AllocConsole(); [DllImport(Kernel32_DllName)] private static extern bool FreeConsole(); [DllImport(Kernel32_DllName)] private static extern IntPtr GetConsoleWindow(); [DllImport(Kernel32_DllName)] private static extern int GetConsoleOutputCP(); public static bool HasConsole { get { return GetConsoleWindow() != IntPtr.Zero; } } /// <summary> /// Creates a new console instance if the process is not attached to a console already. /// </summary> public static void Show() { //#if DEBUG if (!HasConsole) { AllocConsole(); InvalidateOutAndError(); } //#endif } /// <summary> /// If the process has a console attached to it, it will be detached and no longer visible. Writing to the System.Console is still possible, but no output will be shown. /// </summary> public static void Hide() { //#if DEBUG if (HasConsole) { SetOutAndErrorNull(); FreeConsole(); } //#endif } public static void Toggle() { if (HasConsole) { Hide(); } else { Show(); } } static void InvalidateOutAndError() { Type type = typeof(System.Console); System.Reflection.FieldInfo _out = type.GetField("_out", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); System.Reflection.FieldInfo _error = type.GetField("_error", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); System.Reflection.MethodInfo _InitializeStdOutError = type.GetMethod("InitializeStdOutError", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); Debug.Assert(_out != null); Debug.Assert(_error != null); Debug.Assert(_InitializeStdOutError != null); _out.SetValue(null, null); _error.SetValue(null, null); _InitializeStdOutError.Invoke(null, new object[] { true }); } static void SetOutAndErrorNull() { Console.SetOut(TextWriter.Null); Console.SetError(TextWriter.Null); } }
The sample application shows how to:
- Create and start a thread
- Show the console and log the actions of the thread
- Check if the thread is alive or is ended
- Shutdown a thread gracefully from outside
- Joining a thread
- Throw an exception to a thread and handle it
You can download it here: https://www.mesta-automation.com/Downloads/multithread.rar
I was excited about finding this, but no console output is displayed when running in Visual Studio 2017.