-1

I have simple program using C# with WPF and when the program initializes I want the button color to become green and after 1 second become red. But when I use my program with Thread.Sleep(1000), it does not become red after 1 second. This might show I know something fundamentally wrong here. Below is the entire code I tried:

enter image description here

<Window x:Class="TestEventHandler.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TestEventHandler"
        mc:Ignorable="d"
        Title="MainWindow" Height="250" Width="250">
    <Grid>

        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />

        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="7*" />
            <ColumnDefinition Width="389*"/>

        </Grid.ColumnDefinitions>

        <Button Grid.Row="0" Grid.Column="0" x:Name="MyButton" Grid.ColumnSpan="2" Click="MyButton_Click">MyButton</Button>
        <Label  Grid.Row="1" Grid.Column="0" x:Name="MyLabel" Grid.ColumnSpan="2" HorizontalContentAlignment="Center" VerticalContentAlignment="Center">MyLabel</Label>

    </Grid>
</Window>

And here is the program logic:

using System.Threading;
using System.Windows;
using System.Windows.Media;

namespace TestEventHandler
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void MyButton_Click(object sender, RoutedEventArgs e)
        {
            MyLabel.Background = Brushes.Red;
            Thread.Sleep(1000);
            MyLabel.Background = Brushes.Green;
        }
    }
}

How can it be done that when the program initializes the button is green and the a second later the button color becomes red? What is a good and stable practice for that? Should I use Stopwatch?

Dominik
  • 1,623
  • 11
  • 27
cm64
  • 121
  • 5
  • 3
    You do it in a `click` `event`, so your `label` will only become red after you clicked it. – Dominik Mar 17 '21 at 13:01
  • Using `Thread.Sleep(1000)` on the UI thread is a bad idea because it makes the UI not-responsive. If you are going to do this, you could as well adopt another bad practice, and sprinkle your code with [`Application.DoEvents()`](https://blog.codinghorror.com/is-doevents-evil/). Placing one `DoEvents` before every `Thread.Sleep` will fix the problem in a dirty way. – Theodor Zoulias Mar 17 '21 at 13:41
  • @TheodorZoulias Thanks for the comment. Is Application.DoEvents() helpful when interacting with GUI part of the code? In the same project I also need to use Thread.Sleep(200) for serial communications between sending and receiving commands between port.Write and port.Read. Because the response is not fast enough. If I don't use Thread.Sleep() I get wrong data. Do you think in such scenario where there is no GUI involved Application.DoEvents() still necessary? – cm64 Mar 17 '21 at 13:46
  • _"Is Application.DoEvents() helpful when interacting with GUI part of the code?"_ -- no. The comment from @Theodor was not meant to be taken seriously. It's not even _accurate_, because you're still going to get 1-second delays in the UI responsiveness as long as `Thread.Sleep()` is used, even if you do call `DoEvents()` (which you should **never** do). – Peter Duniho Mar 17 '21 at 21:49

2 Answers2

1

Instead of Thread.Sleep use Task.Delay like this

private async void MyButton_Click(object sender, RoutedEventArgs e)
{
    MyLabel.Background = Brushes.Red;
    await Task.Delay(1000);
    MyLabel.Background = Brushes.Green;
}

Have a look at this: When to use Task.Delay, when to use Thread.Sleep?

Here an entry point regarding the async/await pattern and Tasks

https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/

Rand Random
  • 7,300
  • 10
  • 40
  • 88
  • in the same project I also need to use Thread.Sleep(200) for serial communications between sending and receiving commands between port.Write and port.Read. Because the response is not fast enough. If I don't use Thread.Sleep() I get wrong data. Do you think in that case Thread-Sleep is the way to go rather than Task.Delay? – cm64 Mar 17 '21 at 14:02
  • 1
    @cm64 - I would suggest asking a new question, since I have no clue why it would throw an exception using Task, the main difference is it the thread gets blocked yes/no, wouldn't know a reason why serial com would need the thread to be blocked for it to work, sorry - but if Thread.Sleep doesn't give problem, and you don't care if the thread gets blocked or not it is still valid to use, in this scenario you don't want the thread to block since the first color change need to be process by the thread, can't block it if it should process something – Rand Random Mar 17 '21 at 14:06
1

you need to to put the code in the window_Loaded event so if will run when thw window opens.

 private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        MyLabel.Background = Brushes.Red;
        Thread.Sleep(1000);
        MyLabel.Background = Brushes.Green;
    }

also, you shuld probebly use await Task.Delay(1000) instead of Thread.Sleep(1000) so the window will stay responsive during that second.

Efraim Newman
  • 927
  • 6
  • 21