C# user interface updates are not deterministic

落花浮王杯 提交于 2019-12-09 23:37:01

问题


UWP application, C#, Visual Studio 2017, Windows 10 Creators Update (10.0; Build 15063).

Let's call TextBlock1 as T1, TextBlock2 as T2... Desired output is:

T1 shows "Work started."

T2 shows "Step 1"

T2 shows "Step 2"

T2 shows ""

T1 shows "Work Finished."

    private async void Btn_Click(object sender, RoutedEventArgs e)
    {
        TextBlock1.Text = "Work started.";
        await DoWork();
        TextBlock1.Text = "Work done.";
    }

    private async Task DoWork()
    {
        TextBlock2.Text = "Step 1";
        await Task.Delay(1); //Pretend to do something
        TextBlock2.Text = "Step 2";
        await Task.Delay(1); //Pretend to do something
        TextBlock2.Text = "";
    }

When I debug, actual output is non-deterministic:

1: TextBlock updates only happen when I step into an await or when the event handler closes.

2: Sometimes TextBlock updates occur at await #1, sometimes at await #2, sometimes at both, and sometimes at neither.

3: Regardless of prior events, T1 will show "Work done." and T2 will show "" at the end of Btn_Click().

When I request a UI update, I want the program to do nothing except what's necessary to perform the update. It should not proceed to my next request before the update is shown on the UI.

I've spent days on this. Is it possible?

I've found a way to remove the non-deterministic aspect of this problem. But I don't really understand what's happening, and it still doesn't meet the requirement in bold above:

    private async Task UpdateTextInUI(TextBlock textBlock, string str)
    {
        await textBlock.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            new DispatchedHandler(() => { textBlock.Text = str; }));
    }

回答1:


Let me break it down for you:

  1. TextBlock updates only happen when I step into an await or when the event handler closes.

This is perfectly normal. The await call basicly does the next thing: start the given function, and until that is ongoing return to the callee. This also implies, that when your awaited function returns, the scope immideatly returns to after the await. So, if your awaited function is really quick, then the UI might not have enough time to apply your changes.

  1. Sometimes TextBlock updates occur at await #1, sometimes at await #2, sometimes at both, and sometimes at neither.

Same as the above, sometimes the UI has enough time, sometimes it doesn't. That's the funny thing with threads. They are non-deterministic.

  1. Regardless of prior events, T1 will show "Work done." and T2 will show "" at the end of Btn_Click().

After the DoWork function completes, the UI gains back full control, so it can apply all your changes -> the last Text values get applied.

Edit:

If you really want the UI to update, you can await Task.Yield(). This will force the UI to gain back control.



来源:https://stackoverflow.com/questions/47557626/c-sharp-user-interface-updates-are-not-deterministic

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!