Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu öğreticide, bir C# zaman uyumsuz uygulamasında hata ayıklamak için Paralel Yığınlar penceresinin Görevler görünümünün nasıl kullanılacağı gösterilmektedir. Bu pencere, Görev tabanlı zaman uyumsuz desen (TAP) olarak da adlandırılan zaman uyumsuz/await desenini kullanan kodun çalışma zamanı davranışını anlamanıza ve doğrulamanıza yardımcı olur.
Görev Paralel Kitaplığı'nı (TPL) kullanan ancak zaman uyumsuz/await desenini kullanmayan uygulamalar için veya Eşzamanlılık Çalışma Zamanı'nı kullanan C++ uygulamaları için, hata ayıklama için Paralel Yığınlar penceresindeki İş Parçacıkları görünümünü kullanın. Daha fazla bilgi için bkz. Kilitlenme hatalarını ayıklama ve Paralel Yığınlar penceresinde iş parçacıklarını ve görevleri görüntüleme.
Görevler görünümü şunları oluşturmanıza yardımcı olur:
Asenkron/await desenini kullanan uygulamalar için çağrı yığını görsellerini görüntüleyin. Bu senaryolarda Görevler görünümü, uygulama durumunuzun daha eksiksiz bir resmini sağlar.
Çalışmak üzere zamanlanmış ancak henüz çalışmayan eşzamansız kodu belirleyin. Örneğin, veri döndürmeyen bir HTTP isteğinin, sorunu yalıtmanıza yardımcı olan İş Parçacıkları görünümü yerine Görevler görünümünde görünme olasılığı daha yüksektir.
Eşzamanlı üstü eşzamansız (sync-over-async) düzeni gibi sorunların yanı sıra engellenmiş veya bekleyen görevler gibi potansiyel sorunlarla ilgili ipuçlarını belirlemeye yardımcı olun. Sync-over-async kod paterni, zaman uyumsuz yöntemleri zaman uyumlu bir şekilde çağıran koda atıfta bulunur. Bu kodun iş parçacıklarını engellediği bilinir ve iş parçacığı havuzu yetersizliğinin en yaygın nedenidir.
Asenkron çağrı yığınları
Paralel Yığınlar'daki Görevler görünümü, zaman uyumsuz çağrı yığınları için bir görselleştirme sağlar, böylece uygulamanızda neler olduğunu (veya olması gerekenleri) görebilirsiniz.
Görevler görünümünde verileri yorumlarken hatırlamanız gereken birkaç önemli nokta aşağıdadır.
Zaman uyumsuz çağrı yığınları, yığını temsil eden fiziksel çağrı yığınları değil mantıksal veya sanal çağrı yığınlarıdır. Zaman uyumsuz kodla çalışırken (örneğin anahtar sözcüğünü
awaitkullanarak), hata ayıklayıcı "zaman uyumsuz çağrı yığınları" veya "sanal çağrı yığınları" görünümünü sağlar. Zaman uyumsuz çağrı yığınları şu anda herhangi bir fiziksel iş parçacığında çalıştırılmadığından, zaman uyumsuz çağrı yığınları iş parçacığı tabanlı çağrı yığınlarından veya "fiziksel yığınlardan" farklıdır. Bunun yerine, zaman uyumsuz çağrı yığınları, gelecekte zaman uyumsuz olarak çalışacak kodun devamlılıkları veya "vaatleri"dir. Çağrı yığınları devamlılıklar kullanılarak oluşturulur.Zamanlanmış ancak şu anda çalışmayan zaman uyumsuz kod fiziksel çağrı yığınında görünmez, ancak Görevler görünümünde zaman uyumsuz çağrı yığınında görünmelidir. Eğer
.Waitveya.Resultgibi yöntemleri kullanarak iş parçacıklarını engelliyorsanız, kodu bunun yerine fiziksel çağrı yığınında görebilirsiniz.Zaman uyumsuz sanal çağrı yığınları,
.WaitAnyveya.WaitAllgibi yöntem çağrılarının kullanımından kaynaklanan dallanma nedeniyle her zaman sezgisel değildir.Çağrı Yığını penceresi, geçerli yürütülen iş parçacığı için fiziksel çağrı yığınını gösterdiğinden Görevler görünümüyle birlikte yararlı olabilir.
Sanal çağrı yığınının aynı bölümleri, karmaşık uygulamalar için görselleştirmeyi basitleştirmek üzere birlikte gruplandırılır.
Aşağıdaki kavramsal animasyon, gruplandırma işleminin sanal çağrı yığınlarına nasıl uygulandığını gösterir. Sanal çağrı yığınının yalnızca özdeş kesimleri gruplandırılır. Görevleri çalıştıran iş parçacıklarını belirlemek için gruplandırılmış çağrı yığınının üzerine gelin.
C# örneği
Bu kılavuzdaki örnek kod, bir gorilin hayatında bir gün simülasyonu sağlayan bir uygulamaya yöneliktir. Alıştırmanın amacı, zaman uyumsuz bir uygulamada hata ayıklamak için Paralel Yığınlar penceresinin Görevler görünümünün nasıl kullanılacağını anlamaktır.
Örnek, iş parçacığı havuzu açlığıyla sonuçlanabilecek senkron üzerinden asenkron antipattern kullanımına bir örnek içerir.
Çağrı yığınını sezgisel hale getirmek için örnek uygulama aşağıdaki sıralı adımları gerçekleştirir:
- Gorilleri temsil eden bir nesne oluşturur.
- Goril uyanır.
- Goril sabah yürüyüşüne çıkıyor.
- Goril ormanda muz bulur.
- Goril yiyor.
- Goril maymun işine girer.
Örnek projeyi oluşturma
Visual Studio'yu açın ve yeni bir proje oluşturun.
Başlangıç penceresi açık değilse Dosya
Başlangıç Penceresi seçin. Başlangıç penceresinde Yeni proje'yi seçin.
Yeni proje oluştur penceresinde, arama kutusuna konsol girin veya yazın. Ardından, Dil listesinden C# seçin ve ardından Platform listesinden windows seçin.
Dil ve platform filtrelerini uyguladıktan sonra .NET için Konsol Uygulaması'nı ve ardından İleri'yi seçin.
Uyarı
Doğru şablonu görmüyorsanız Visual Studio Yükleyicisi'ni açan Araçlar>Araç ve Özellik Al... seçeneğine gidin. .NET masaüstü geliştirme iş yükünü seçin ve ardından Değiştir'iseçin.
Yeni projenizi yapılandırın penceresinde, proje adı kutusuna bir ad yazın veya varsayılan adı kullanın. Ardından İleri'yi seçin.
.NET için önerilen hedef çerçeveyi veya .NET 8'i ve ardından Oluştur'u seçin.
Yeni bir konsol projesi görünür. Proje oluşturulduktan sonra bir kaynak dosya görüntülenir.
Projede .cs kod dosyasını açın. Boş bir kod dosyası oluşturmak için içeriğini silin.
Seçtiğiniz dil için aşağıdaki kodu boş kod dosyasına yapıştırın.
using System.Diagnostics; namespace AsyncTasks_SyncOverAsync { class Jungle { public static async Task<int> FindBananas() { await Task.Delay(1000); Console.WriteLine("Got bananas."); return 0; } static async Task Gorilla_Start() { Debugger.Break(); Gorilla koko = new Gorilla(); int result = await Task.Run(koko.WakeUp); } static async Task Main(string[] args) { List<Task> tasks = new List<Task>(); for (int i = 0; i < 2; i++) { Task task = Gorilla_Start(); tasks.Add(task); } await Task.WhenAll(tasks); } } class Gorilla { public async Task<int> WakeUp() { int myResult = await MorningWalk(); return myResult; } public async Task<int> MorningWalk() { int myResult = await Jungle.FindBananas(); GobbleUpBananas(myResult); return myResult; } /// <summary> /// Calls a .Wait. /// </summary> public void GobbleUpBananas(int food) { Console.WriteLine("Trying to gobble up food synchronously..."); Task mb = DoSomeMonkeyBusiness(); mb.Wait(); } public async Task DoSomeMonkeyBusiness() { Debugger.Break(); while (!System.Diagnostics.Debugger.IsAttached) { Thread.Sleep(100); } await Task.Delay(30000); Console.WriteLine("Monkey business done"); } } }Kod dosyasını güncelleştirdikten sonra değişikliklerinizi kaydedin ve çözümü oluşturun.
Dosya menüsünde Tümünü Kaydet'i seçin.
Derle menüsünde Çözüm Derle'yi seçin.
Paralel Yığınlar penceresinde Görevler Görünümünü kullanın
Hata Ayıkla menüsünde Hata Ayıklamayı Başlat 'ı (veya F5) seçin ve ilkin
Debugger.Break()isabetini bekleyin.F5 tuşuna bir kez bastığınızda hata ayıklayıcı aynı
Debugger.Break()satırda yeniden duraklatılır.Bu, ikinci bir zaman uyumsuz görev içinde gerçekleşen
Gorilla_Start'nin ikinci çağrısında duraklar.Paralel Yığınlar penceresini açmak için Windows > Paralel Yığınlarında Hata Ayıkla'yı > seçin ve ardından penceredeki Görünüm açılan listesinden Görevler'i seçin.
Zaman uyumsuz çağrı yığınlarının etiketlerinin 2 Zaman Uyumsuz Mantıksal Yığını açıkladığına dikkat edin. F5'e en son bastığınızda başka bir görev başlattınız. Karmaşık uygulamaları basitleştirmek amacıyla, özdeş asenkron çağrı yığınları tek bir görsel temsil içinde bir araya getirilir. Bu, özellikle birçok görevi olan senaryolarda daha eksiksiz bilgiler sağlar.
Görevler görünümünün aksine, Çağrı Yığını penceresi yalnızca geçerli iş parçacığının çağrı yığınını gösterir, birden çok görev için değil. Uygulama durumunun daha eksiksiz bir resmi için her ikisini birlikte görüntülemek genellikle yararlı olur.
Tavsiye
Çağrı Yığını penceresi, açıklamasını
Async cyclekullanarak kilitlenme gibi bilgileri gösterebilir.Hata ayıklama sırasında dış kodun görüntülenip görüntülenmeyeceğini değiştirebilirsiniz. Özelliği değiştirmek için Çağrı Yığını penceresinin Ad tablosu üst bilgisine sağ tıklayın ve Dış Kodu Göster seçeneğini seçin veya kaldırın. Dış kod gösterirseniz, bu kılavuzu kullanmaya devam edebilirsiniz, ancak sonuçlarınız çizimlerden farklı olabilir.
F5 tuşuna yeniden basın, hata ayıklayıcı
DoSomeMonkeyBusinessyönteminde durur.
Bu görünüm,
awaitve benzeri yöntemler kullanılırken iç devamlılık zincirine daha fazla zaman uyumsuz yöntem eklendikten sonra, daha eksiksiz bir zaman uyumsuz çağrı yığını gösterir.DoSomeMonkeyBusinesszaman uyumsuz bir yöntem olduğundan ancak devam zincirine henüz eklenmediği için zaman uyumsuz çağrı yığınının en üstünde bulunabilir veya olmayabilir. İzleyen adımlarda bunun neden böyle olduğunu keşfedeceğiz.Bu görünümde
Jungle.Main
simgesi de gösterilir. Bu bilgilendiricidir, ancak genellikle bir sorunu göstermez. Diğer bir görevin bitmesini bekleyen, bir olayın tetiklenmesini ya da kilidin serbest bırakılmasını beklediği için engellenen görev, engellenmiş bir görevdir.GobbleUpBananasyönteminin üzerine gelin ve görevleri çalıştıran iki iş parçacığı hakkında bilgi edinin.
Geçerli iş parçacığı, Debug araç çubuğundaki İş Parçacığı listesinde de görünür.
Hata ayıklayıcısı bağlamını farklı bir iş parçacığına değiştirmek için İş Parçacığı listesini kullanabilirsiniz.
F5 tuşuna yeniden basın ve hata ayıklayıcı ikinci görevin metotunda durur.
Görevin yürütülme zamanına bağlı olarak, bu noktada ya ayrı ya da gruplandırılmış eşzamanlı olmayan çağrı yığınlarını görürsünüz.
Yukarıdaki çizimde, iki görev için zaman uyumsuz çağrı yığınları ayrıdır çünkü bunlar özdeş değildir.
F5 tuşuna yeniden bastığınızda uzun bir gecikme olduğunu görürsünüz ve Görevler görünümünde zaman uyumsuz çağrı yığını bilgisi gösterilmez.
Gecikme, uzun süre çalışan bir görevden kaynaklanır. Bu örnek amacıyla, bir web isteği gibi uzun süre çalışan bir görevin simülasyonunu gerçekleştirir; bu da iş parçacığı havuzu yoksunluğuna neden olabilir. Görevler engellenmiş olsa bile hata ayıklayıcıda şu an duraklatılmadığınız için Görevler görünümünde hiçbir şey görünmez.
Tavsiye
Kilitlenme oluşursa veya tüm görevler ve iş parçacıkları şu anda engellenirse Tümünü Kes düğmesi çağrı yığını bilgilerini almak için iyi bir yoldur.
Hata Ayıklama araç çubuğundaki IDE'nin üst kısmında Tümünü Kes düğmesini (duraklat simgesi), Ctrl + Alt + Break'i seçin.
Görevler görünümünde, zaman uyumsuz çağrı yığınının üst kısmında
GobbleUpBananasengellenmiş olduğunu görürsünüz. Aslında iki görev aynı noktada engellenir. Engellenen görev beklenmedik olmayabilir ve bir sorun olduğu anlamına gelmez. Ancak, yürütmede gözlemlenen gecikme bir sorunu gösterir ve buradaki çağrı yığını bilgileri sorunun konumunu gösterir.Önceki ekran görüntüsünün sol tarafında, kıvrılmış yeşil ok geçerli hata ayıklayıcı bağlamını gösterir.
mb.Wait()'da iki görevGobbleUpBananasyönteminde engellenir.Çağrı Yığını penceresi, geçerli iş parçacığının engellendiğini de gösterir.
çağrısı,
Wait()zaman uyumlu çağrısı içindeki iş parçacıklarınıGobbleUpBananasengeller. Bu, senkron-üzerinden-asenkron anti-deseninin bir örneğidir; eğer bu durum bir UI iş parçacığında veya büyük işleme iş yükleri altında meydana gelirse, genellikleawaitkullanılarak bir kod düzeltmesi ile giderilir. Daha fazla bilgi için bkz. İş parçacığı havuzu açlığını giderme. İş parçacığı havuzu yetersizliğinde hata ayıklamak için profil oluşturma araçlarını kullanmayı öğrenmek amacıyla bkz Vaka incelemesi: Performans sorununu yalıtma.Ayrıca ilginç olan,
DoSomeMonkeyBusinessçağrı yığınında görünmez. Şu anda çalışmıyor, yalnızca zamanlanmıştır, bu nedenle yalnızca Görevler görünümündeki eşzamansız çağrı yığınında görünür.Tavsiye
Hata ayıklayıcısı iş parçacığı başına koda girer. Örneğin, yürütmeye devam etmek için F5 tuşuna basarsanız ve uygulama bir sonraki kesme noktasına ulaştığında, farklı bir iş parçacığındaki koda geçebilir. Hata ayıklama amacıyla bunu yönetmeniz gerekiyorsa, ek kesme noktaları ekleyebilir, koşullu kesme noktaları ekleyebilir veya Tümünü Kes'i kullanabilirsiniz. Bu davranış hakkında daha fazla bilgi için bkz. Koşullu kesme noktalarıyla tek bir iş parçacığını izleme.
Örnek kodu düzeltme
GobbleUpBananasyöntemini aşağıdaki kodla değiştirin.public async Task GobbleUpBananas(int food) // Previously returned void. { Console.WriteLine("Trying to gobble up food..."); //Task mb = DoSomeMonkeyBusiness(); //mb.Wait(); await DoSomeMonkeyBusiness(); }yönteminde
MorningWalkkullanarakawaitGobbleUpBananas'ı çağırın.await GobbleUpBananas(myResult);Yeniden Başlat düğmesini (Ctrl + Shift + F5) seçin ve ardından uygulama "askıda" görünene kadar F5 tuşuna birkaç kez basın.
Hepsini Sonlandır'a basın.
Bu sefer
GobbleUpBananasuyumsuz olarak çalışır. Kod durduğunda, asenkron çağrı yığınını görürsünüz.
Çağrı Yığını penceresi
ExternalCodegirişi dışında boştur.Kod düzenleyicisi bize hiçbir şey göstermez, ancak tüm iş parçacıklarının dış kodu yürüttüğüne dair bir ileti sağlar.
Ancak Görevler görünümü yararlı bilgiler sağlar.
DoSomeMonkeyBusinessbeklendiği gibi asenkron çağrı yığınının en üstündedir. Bu, uzun süre çalışan yöntemin nerede bulunduğunu doğru bir şekilde bildirir. Bu, çağrı yığını penceresinde yer alan fiziksel çağrı yığını yeterli ayrıntı sağlamadığında, async/await sorunlarını izole etmekte faydalıdır.
Özet
Bu kılavuzda Parallel Stacks hata ayıklayıcısı penceresi gösterilmiştir. Asenkron/await desenini kullanan uygulamalarda bu pencereyi kullanın.