0

I have read many answers on this question, and yet I still cannot get this to work. I have a simple C# WinForms app with a timer control. When the timer fires, I have some code do some processing. I want to update a textbox with status during this processing. But the textbox never gets updated until the eventhandler finishes. Please tell me how I can get the textbox to update during the processing.

Here is my code:

My Form:

public Form1()
{
    InitializeComponent();

    timer1.Interval = 60000;
    timer1.Tick += new EventHandler(CheckStatus);

    timer1.Start();
}

private void CheckStatus(object Sender, EventArgs e)
{
    // Set the caption to the current time.              
    textBox1.AppendText(DateTime.Now.ToString() + Environment.NewLine);
    ProcessStatus();
}

private void ProcessStatus()
{
    textBox1.AppendText("Now updated" + Environment.NewLine);
}

If I step through my code, the textbox is not updated until I step out of CheckStatus. (I'm using Visual Studio 2017)

I have tried several things like what is found here: StackOverflow

Hossein Golshani
  • 1,847
  • 5
  • 16
  • 27
TheBigOnion
  • 615
  • 3
  • 9
  • 19

1 Answers1

1

When the timer ticks it's firing on the GUI thread. While the GUI thread is busy processing (I assume whatever you're doing takes a long time) all other GUI updates will pause.

You can run textBox.Update() to force the update at that point, but that's not considered a best practice.

Instead, you should run your process on a background thread. One option is BackgroundWorker and use the ProgressChanged event to show your updates in your GUI.

MikeH
  • 4,242
  • 1
  • 17
  • 32
  • This is accurate, but `BackgroundWorker` is deprecated and may not work in newer .Net versions. A more modern approach is to use a `Task` (`Task.Run()` or `TaskFactory.StartNew()`) and then to use `Invoke()` to perform actions on the GUI thread. Either approach accomplishes the same thing - they push your logic onto a background thread so that the GUI thread can be updated. – Dave Smash Oct 10 '18 at 18:55
  • Pete, that makes sense. I am not familiar with those functions. Could you show me how those would be used in my code above? – TheBigOnion Oct 10 '18 at 18:55
  • @ElementalPete I agree that you could use a `Task`, but I like `BackgroundWorker` for single thread tasks (just a preference). I hadn't heard that it would be deprecated, do you have a source for that? – MikeH Oct 10 '18 at 19:01
  • @TheBigOnion here's an example that's similar to what you are trying to do using `Task.Run` https://blog.stephencleary.com/2012/02/reporting-progress-from-async-tasks.html – MikeH Oct 10 '18 at 19:06
  • 1
    *... all other GUI updates will pause* is not actually correct. The system doesn't draw immediatelly the `textbox` not because the system is busy but because it is designed to do so. What I mean is `drawing` is the absolutely last thing that will happen that is why when `CheckStatus` returns **then** the drawing occurs. Of cource, as you correctly point out calling `update` it will force the system to immediatelly draw the `textbox`. – γηράσκω δ' αεί πολλά διδασκόμε Oct 10 '18 at 19:09
  • @MikeH - Hmmm, a quick Google search isn't turning up anything, so maybe I'm wrong. I thought I had heard years ago that it wouldn't be migrated into .Net Core or Standard, but it seems that maybe they kept it around after all! My apologies. – Dave Smash Oct 10 '18 at 19:09
  • @γηράσκωδ'αείπολλάδιδασκόμε Thanks for the clarification! – MikeH Oct 10 '18 at 19:10