Search code examples
c#.netwpfmessagebox

What does messageBox.Show() do in order to stop the execution of a UI thread?


In a WPF application, I am outputting messages to a text box and in between these messages I am calling a function that sets up an instrument. However the messages all appear at the same time (at end of function call).

I do not really know how to explain my problem clearly. I'll try... I have a WPF application which takes data from an instrument using the serial port. The application contains some buttons and a text box for output messages. Upon pressing a button, the application sends a command to the instrument to change some parameters (through a function Set_COMM_MODE()), and returns. The change takes around 5-10 seconds. Thus what I did is: I outputted a "Please Wait" message before the call and a "Done" message after the call return. The OuputText() function in the code only calls the TextBox.AppendText() method. My Problem: All the output text is splurted out on the text box upon the call return. I expected a Please Wait... then 5-10s later a "Done" message. But it is all appearing at the same time. However, when I put a MessageBox after the 1st message (before the function call), the message appears on the textbox output (w/o the function being called). However the problem is that I have to press OK on the MessageBox in order to continue.

Q(1): How can I have the latter happening w/o having to resort to a MessageBox
Q(2): What does a MessageBox do in order to create this behaviour?

I tried: using the Dispatch.Invoke() method to run the OutputText on another thread. This (Pause a window like MessageBox.Show()) is a similar problem to what I have, but didn't seem to get a definitive answer, and I did not understand the solution well.

void StartTest_btn_Click(object sender, RoutedEventArgs e)
{
    OutputText("Please Wwait\r\n"); //<---- This should appear at once.

    MessageBox.Show("Please Wwait"); //<--without this, both messages appear at same time after 10s.

    Set_COMM_MODE("02"); //<--- This takes around 5-10s

    OutputText("Done\r\n"); //<--- This should appear 5-10s later
}

I expect a "Please wait" to show at once, then 5-10s later the "Done" message to show, after return of function Set_COMM_MODE().


Solution

  • As I wrote in my comment, you should really use the (main) UI thread for UI only. Perform any other long-running non-UI operations on worker threads.

    You might not mind the "hang" UI for 10 seconds, but users will surely be annoyed. Also, blocking the UI thread will cause Windows to think that your app is frozen, so you'll get that nice "not responding" badge and all related stuff. This not only looks awful but also can cause various side-effects.

    You should really take a look around and see what .NET offers you for such kind of problems.

    Look, this is your workflow:

    1. Print a message
    2. Start initialization
    3. ???
    4. Initialization is complete --> print "done"
    5. Start operation

    What is this? This is an asynchronous processing. You start an action and continue asynchronously - that means, only when the action is completed.

    .NET offers you a lot of tools for that, e.g. the APM (Asynchronous Programming Model). But the most neat and powerful way for implementing asynchronous processing is the TAP - Task-based Asynchronous Programming pattern, better known as async/await.

    Look, your problem can be solved with a couple of lines using the TAP:

    async void StartTest_btn_Click(object sender, RoutedEventArgs e)
    {
        OutputText("Please Wait\r\n");      
    
        // Set_COMM_MODE will be executed on a worker thread!
        // The main (UI) thread won't block. It will continue.
        // But the StartTest_btn_Click method itself will pause until the task is finished.
        await Task.Run(() => Set_COMM_MODE("02"));
    
        // This line will only be executed, after the Set_COMM_MODE call is completed;
        // furthermore, it will be executed on the UI thread again!
        OutputText("Done\r\n");
    }
    

    You should really learn more about the modern programming techniques, which the TAP is one of.