2012-07-03 7 views
24

, await GetFileAsync("filename.xml"); böylece döner asla WinRT uygulamasında kapatır) GetFileAsync (beklemek üzere .Çağrı asla döner ve uygulama uygulama asılı, ben yüklemek ve uygulama başlatılması üzerine bir ayar dosyasını okumak ve zamanın yaklaşık% 90 çalışılıyor

Saatin yaklaşık dörtte biri, kodun içinden geçersem, aslında dosyayı döndürür ve okuyacaktır. Ben Visual Studio Çıktı penceresini izlersen

public async static Task Load() 
{ 
    StorageFolder folder = ApplicationData.Current.LocalFolder; 
    StorageFile file; 
    bool fileExists = true; 

    try 
    { 
     // The following line (often) never returns 
     file = await folder.GetFileAsync("filename.xml"); 
    { 
    catch 
    { 
     fileExists = false; 
    } 

    // Do stuff with loaded file 
} 

:

App.xaml.cs:

protected override void OnLaunched(LaunchActivatedEventArgs args) 
{ 
    FileLoader.Load().Wait(); 

    // File-load dependent stuff 
} 

FileLoader.cs

İşte kod çok basitleştirilmiş versiyonu beklemeden bir süre sonra "The thread '<No Name>' (0x30c) has exited with code 0 (0x0)."

Herhangi bir fikri olan var mı? Burada neler oluyor? Varsayılan olarak

+6

UI iş parçacığını, 'Bekle' diyerek görebileceğim kadar engellemiyorsunuz. Bu gerçekten kötü bir fikir. Heck, bu soruna neden olan olabilir. –

+1

Bence Jon tam olarak doğru - OnLaunched'ı async olarak işaretleyip daha sonra Load() çağrısını beklemek için herhangi bir şans? Yapamazsanız, başka bir yaklaşım yükün bittikten sonra yürütülmesi için bir eylemi gerçekleştirmesi ve ardından eylemi sonlandırması olabilir (veya elbette, Load() işlevinin döndürdüğü görevde ContinueWith'i kullanabilirsiniz. aynen async/beklemeden önceki gibi :) –

+0

İkiniz de haklısınız Jon ve James. Giriş için çok teşekkür ederim! Orijinal olarak "Wait" kullanıyordum çünkü geçersiz kılınmış bir yönteme "async" ekleyebileceğinizi fark etmedim ve "OnLaunched" in UI iş parçacığı üzerinde çalıştığını bilmiyordum. 'Bekle '' kaldırılıyor ve' OnLaunched''e 'async 'eklendiğinde hata düzeltildi! Yorumlarınızı cevap olarak işaretleyebilirdim. – jokeefe

cevap

47

, ne zaman henüz tamamlanmamış bir Task, yöntem (bu durumda, UI bağlam içinde) bir esir bağlama devam await. kodunuzu başarısız neden

Yani, burada: (UI kapsamında)

  • OnLaunched aramalar Load.
  • Load sizi bekliyor. Bu, Load yönteminin tamamlanmamış bir görevi döndürmesine ve tamamlanmasının daha sonra yapılması planlanmasına neden olur. Bu devam, UI içeriği için planlandı. Görevdeki
  • blokları Load'dan döndü. Bu, UI iş parçacığını engeller.
  • GetFileAsync sonunda tamamlanır ve Load için devamlamayı çalıştırmaya çalışır. Load1'in devamı UI dizgesinin UI bağlamında çalışabilmesi için kullanılabilir olmasını bekler.
  • Bu noktada, Load'u tamamlamak (bunu yaparak UI iş parçacığı engellemek) ve Load UI iş parçacığının serbest olmasını bekliyor. Kilitlenme.

Bunlar en iyi uygulamaları bu durumdan kaçınmak: Mümkün async yöntemlerle sizin "kitaplık" olarak

  1. , ConfigureAwait(false) kullanın. Durumunuzda, bu await folder.GetFileAsync("filename.xml"); değerini await folder.GetFileAsync("filename.xml").ConfigureAwait(false); olarak değiştirecektir.
  2. Task s; async tamamen aşağı doğru. Başka bir deyişle, Wait'u await ile değiştirin.Daha fazla bilgi için

:

Task awaiters SynchronizationContext kullanımıyla ilgili kısa bir açıklama içerir ve bazı en iyi uygulamaları tanıtır Benim async/await intro post

Update 2012/07/13: bu cevabı into a blog post Incorporated.

+0

Mükemmel cevap! Nelerin olup bittiğine dair ayrıntılı açıklama ve referans makalelerden oluşan kapsamlı bir liste için çok teşekkür ederiz. Bu her şeyi daha net hale getirir. – jokeefe

+0

Bu mükemmeldi. Bu beni çok üzdü, inanılmazdı. – ohmusama

+1

MS'in ölmesini diliyorum. Kesinlikle çılgın şeyler sağladıkları için insanları arıyorlar. Neden eski moda konuları bırakıp ilkelikleri senkronize etmediler ?! Moronlar. –

İlgili konular