1
votes

I have an WPF application using the MVVM design property. There is a long running process to populate a grid that I would like to show a busy cursor for. I have the part changing the cursor working. The problem I have is that the cursor is bound to a bool called IsBusy. When the method is called that runs for awhile I set IsBusy to true and when the method is complete I set it back to false.

public void LongProcedure(){ IsBusy=true; ... long running code here IsBusy=false; } `

I know the cursor binding to IsBusy is working because I tested it out with another procedure that does

IsBusy=!IsBusy;

And that does toggle the cursor. The problem I am having is that the view doesn't appear to refresh while the code in the method is running. Is there a way to force the view to refesh after I set IsBusy to true?

1
Are you performing the long running task on the same thread?XAMlMAX
Yes, I was hoping to keep it simple. The process takes between 5-10 seconds and they can't do anything else while it is running. I wanted to show the wait cursor just to let the user know something was happening.Pedler
@Pedler Unfortunately, the same thread is needed to update the screen. With it running something else, it can't be used to update the screen.Aron
Dear lord, please reveal unto me the canonical dupe target for how to not block the UI thread while working in the UI thread, praise your name. Amen. ... ... wait, maybe this will be it? I think it is. Get ready for undue upvotes, Pedler!user1228

1 Answers

3
votes

In every windowed application, there is a single thread that is dedicated to working with the visual representation of the application. This thread is the UI thread. When your code runs in response to a window event (e.g., the Loaded event or a user clicking on a button), it is running on this UI thread. While your code runs, the UI thread is occupied performing your work, and cannot update the visual representation of the window. In extreme cases (i.e., your work takes a perceptible amount of time to complete), your window will appear locked up.

If you are performing long-running work using UI thread, then you are not doing it right. You should either use async-await, or use Task.Run() in order to perform your work on a background thread.

If LongProcedure() is IO-bound (like waiting for data from somewhere), then you should use async-await. If it is CPU-bound (a lot of data processing/calculations), then you should use Task.Run()

Async-await:

public async Task LongProcedure()
{
    IsBusy = true;

    await GetDataFromSomewhereAsync();

    IsBusy = false;
}

public async void CallingMethod()
{
    ......
    await LongProcedure();
}

Task.Run:

public void LongProcedure()
{
    IsBusy = true;
    ... // long running code here
    IsBusy = false;
}
public async void CallingMethod()
{
    ......
    await Task.Run((Action) LongProcedure);
}

Please note that the UI cannot be updated directly from a background thread. Typically you will need to marshal your update code onto the UI thread first. There are a number of different ways to do that, and it depends on what kind of windows application you are using, such as windows forms, WPF, etc.