简体   繁体   English

为什么标签文本没有立即更改?

[英]Why isn't the label text changed instantly?

I was trying to test the speed of ModernHttpClient , when I encountered the following: the label isn't updated and neither the button is disabled at once in the following code (tested on Nexus 5x), but rather waits for the click to be processed until the end! 我尝试测试ModernHttpClient的速度时,遇到以下问题:在以下代码中(该标签未在Nexus 5x上进行测试),标签未更新且按钮均未禁用,而是等待处理点击直到最后! What is that, a mistake from my part, a bug or a weird "optimization" feature? 那是什么,我个人的错误,错误或怪异的“优化”功能?

Page1.xaml: 的Page1.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ModernClientBenchmark.Page1">
  <StackLayout>
    <Button Text="Run the test!" Clicked="OnTestClicked" x:Name="btn"></Button>
    <Label Text="here we are" x:Name="labl"/>
  </StackLayout>
</ContentPage>

Page1.xaml.cs: Page1.xaml.cs:

public partial class Page1 : ContentPage
{
    private const int TESTQ = 3;

    public Page1()
    {
        InitializeComponent();
    }

    private async void OnTestClicked(object sender, EventArgs e)
    {
        btn.IsEnabled = false;
        var l1 = new double[TESTQ];
        var l2 = new double[TESTQ];
        for (int i = 0; i < TESTQ; i++)
        {
            Device.BeginInvokeOnMainThread(() => labl.Text = "Step " + i);
            l2[i] = (await ManagedNetworkSpeedAsync(true)).Milliseconds;
            //l1[i] = (await NativeNetworkSpeedAsync(true)).Milliseconds;
        }

        //var avg1 = l1.Sum() / TESTQ;
        //var avg2 = l2.Sum() / TESTQ;

        var a = 234;

    }

    public static async Task<TimeSpan> NativeNetworkSpeedAsync(bool secure)
    {
        using (var client = new HttpClient(new NativeMessageHandler()))
        {
            return await RunTestAsync(secure, client);
        }
    }

    public static async Task<TimeSpan> ManagedNetworkSpeedAsync(bool secure)
    {
        using (var client = new HttpClient())
        {
            return await RunTestAsync(secure, client);
        }
    }

    public static async Task<TimeSpan> RunTestAsync(bool secure, HttpClient client)
    {
        try
        {

            var start = DateTime.Now;
            for (var i = 0; i <= 1; i++)
            {
                var result = client.GetStreamAsync(secure ? "https://xamarin.com" : "http://httpbin.org/ip").Result;
                result.Dispose();
            }
            return DateTime.Now - start;
        }
        catch (Exception ex)
        {
            var a = 234;
        }
        return new TimeSpan();
    }
}

Since you're starting an asynchronous operation and it's being synchronized with the UI thread, the whole label won't change until UI thread has time to perform the whole change. 由于您正在启动异步操作并将其与UI线程同步,因此整个标签不会更改,直到UI线程有时间执行整个更改为止。

This is the regular behavior of modern applications, where you don't want to block the UI for long running operations (ie asynchronous operations like requesting external resources through HTTP). 这是现代应用程序的常规行为,在这种情况下,您不想为长时间运行的操作(例如,通过HTTP请求外部资源之类的异步操作)而阻塞UI。

BTW, you can disable your button before starting the asynchronous operation and enable it again once it has been finished. 顺便说一句,您可以在启动异步操作之前禁用按钮,并在完成异步操作后再次启用它。

You are on already on the UIThread and are blocking yourself, you need to place your work onto the thread pool and update the UI from there, an await Task.Run block will do the job. 您已经在UIThread上并且正在阻塞自己,您需要将工作放到线程池上并从那里更新UI, await Task.Run块将完成此工作。

This will give you the results that you expect: 这将为您提供预期的结果:

private async void OnTestClicked(object sender, EventArgs e)
{
    btn.IsEnabled = false;
    var l2 = new double[TESTQ];
    await Task.Run(async () => {
        for (int i = 0; i < TESTQ; i++)
        {
            Device.BeginInvokeOnMainThread(() => labl.Text = "Step " + i);
            l2[i] = (await ManagedNetworkSpeedAsync(true)).Milliseconds;
        }
    });
    foreach (var x in l2)
    {
        System.Diagnostics.Debug.WriteLine(x);
    }
    btn.IsEnabled = true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM