2016-08-21 7 views
1

私は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(); 
    } 
} 

答えて

1

あなたは既にUIThreadに乗っており、自分自身をブロックしています。あなたは、スレッドプールに作業を置き、そこからUIを更新する必要があります。await Task.Runブロックがその作業を行います。コードは別のスレッドで実行する必要がありますので、私は `await`を使用しています

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; 
} 
1

をあなたは非同期操作を開始しているし、それがUIスレッドと同期されていますので、 UIスレッドが変更全体を実行する時間があるまで、ラベル全体は変更されません。

これは、長期間実行される操作(つまり、HTTPを介した外部リソースのリクエストなどの非同期操作)のUIをブロックしたくない現代的なアプリケーションの通常の動作です。

ところで、非同期操作を開始する前にボタンを無効にして、完了後に再度有効にすることができます。

+0

これは、あなたが期待する結果が得られます。右? – nicks

+0

@NikaGamkrelidzeあなたのケースでは、ええと、BTW async/awaitはそれ自体「他のスレッド」を意味するものではありません。 –

+0

そう、あなたは何を言っているのですか?コードが別のスレッドで実行されている場合、なぜUIスレッドがブロックされますか? – nicks

関連する問題