Question

I have the following code. Within the same block of code, I disable a control then enabled it, but it does not seem to work and remain the initial IsEnable state.

// Button never enable
public void Foo()
{
   button1.IsEnabled = false
   Thread.Sleep(3000);
   button1.IsEnabled = true;
   Thread.Sleep(3000);
   button1.IsEnabled = false;
}
Was it helpful?

Solution

First of all: it isn't that strange that the button is not enabled after the Foo method is done, as the last line disables the button.

If you want to "see" the button's enabled state change, you need to handle window messages before sleeping. Thread.Sleep causes the UI thread to sleep, so there will be no updates to the user interface. What you need to do is make the application handle all pending window messages.

public static void DoEvents()
{
    if (Application.Current != null)
        Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { }));
}

public void Foo()
{
   button1.IsEnabled = false
   DoEvents();
   Thread.Sleep(3000);

   button1.IsEnabled = true;
   DoEvents();
   Thread.Sleep(3000);

   button1.IsEnabled = false;
}

EDIT
Further explanation:

When the first Thread.Sleep is called, the button is disabled (IsEnabled is false). Then, after waiting for 3 seconds, you set the button to enabled, and after that to disable it again. The button is actually in that state, but there is no visual feedback (as in: if you look at the form, you won't see the button "blink").

This is because you are blocking the UI thread by calling Thread.Sleep. This prevents the window from receiving window messages, which tell the window when to repaint itself or one of its children (the button doesn't "know" it should be gray).

So you need to give the window a chance to receive the messages and update its children. In Windows Forms applications, this was done with Application.DoEvents, which processed all pending window messages.

There's no such thing in WPF as Application.DoEvents, but the code I've posted emulates this by spwaning a Thread that does nothing - but that little time between changing the button's enabled state and blocking the UI thread is enough for the button control to repaint itself.

OTHER TIPS

When you call sleep the current thread is suspended and UI will freeze (when you try to click on the UI it will be grayed) until the thread is awakened. So the thread is sleeping for 6 seconds and you will not notice that the button was enabled. At the end the button remains disabled.

You should run your code in another thread using dispatcher.

Ever thought that you might be on the UI-Thread? Read about the dispatcher in wpf.

As stated by others, the UI thread is processing events in the queue. If your function is being called on the UI thread it cannot process updates to the UI until it finishes the current one.

NET does provide a number of threading options like BackgroundWorker, Thread, ThreadPool, etc.

The newer NET framework also provides the async/await method of allowing the GUI thread to do other work during an event.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top