当我遇到以下情况时,我试图测试ModernHttpClient
的速度:标签未更新,并且以下代码中没有立即禁用该按钮(在Nexus 5x上测试),而是等待点击处理直到结束!那是什么,我的错误,错误或奇怪的优化"功能?
的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:
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();
}
}
答案 0 :(得分:1)
由于您正在启动异步操作并且正在与UI线程同步,因此在UI线程有时间执行整个更改之前,整个标签不会更改。
这是现代应用程序的常规行为,您不希望为长时间运行的操作阻塞UI(即通过HTTP请求外部资源等异步操作)。
顺便说一下,您可以在启动异步操作之前禁用您的按钮,并在完成后再次启用它。
答案 1 :(得分:1)
您已经在UIThread上并且正在阻止自己,您需要将您的工作放在线程池上并从那里更新UI,await Task.Run
块将完成这项工作。
这将为您提供您期望的结果:
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;
}