Force redraw before long running operations
Asked Answered
D

3

8

When you have a button, and do something like:

Private Function Button_OnClick

    Button.Enabled = False

    [LONG OPERATION] 

End Function

Then the button will not be grayed, because the long operation prevents the UI thread from repainting the control. I know the right design is to start a background thread / dispatcher, but sometimes that's too much hassle for a simple operation.

So how do I force the button to redraw in disabled state? I tried .UpdateLayout() on the Button, but it didn't have any effects. I also tried System.Windows.Forms.DoEvents() which normally works when using WinForms, but it also had no effect.

Dossier answered 14/11, 2011 at 21:50 Comment(0)
G
8

The following code will do what you're looking for. However I would not use it. Use the BackgroundWorker class for long time operations. It's easy to use and very stable.
Here the code:

   public static void ProcessUITasks() {            
        DispatcherFrame frame = new DispatcherFrame();
        Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(delegate(object parameter) {
            frame.Continue = false;
            return null;
        }), null);
        Dispatcher.PushFrame(frame);
    }

Here you will find a sample on how to use the BackgroundWorker.

Griefstricken answered 14/11, 2011 at 22:2 Comment(4)
He was pretty clear about being aware of but not using a Dispatcher/Backgroundworker :)Wifeless
@edvaldig: I have underlined not to use it, however I have given him the code he was looking for. I don't think that this is worth a -1 from you. If my code does not work, then give me a -1, but not for giving some additional advice. I don't think this is fair.Griefstricken
You're right, I was too quick about it, comment upvote to compensate :)Wifeless
How do you use BackgroundWorker thread if you want to open another application through COM (which I think should be done on the UI thread / STA Apartment) ?Wingard
V
1

In Windows.Forms, you can Button.Refresh().

In Windows.Forms or WPF, you can yield to the message pump to let it redraw. Async/Await were designed to allow you to do this without the nastiness of HCL's answer.

Private Async Function Button_OnClick

    Button.Enabled = False

    Await Task.Yield

    [LONG OPERATION] 

End Function
Varanasi answered 10/6, 2017 at 8:33 Comment(0)
W
0

InvalidateVisual(); @HCL is right... don't do this

Like you say, it is better to start use a background thread / dispatcher and keep the UI thread unblocked. Consider looking at the Reactive Extensions library from Microsoft for high level asynchronous ui programming

Wifeless answered 14/11, 2011 at 21:57 Comment(4)
This will not work. Invalidation does only invalidate the region to be repainted. However it does not the painting.Griefstricken
@HCL, Works fine for me, see the documentation for the function: Invalidates the rendering of the element, and forces a complete new layout pass. OnRender is called after the layout cycle is completed.Wifeless
Are you shure your UI-thread is blocked? I have tested it the last time under .net3.5SP1. At this time it has not worked. If it works now, they must have changed the behaviour with 4.0. However, this would be a big surprise to me.Griefstricken
Does reactive solve the problem of long operation on COM which should be done on the UI thread (STA apartment) ?Wingard

© 2022 - 2024 — McMap. All rights reserved.