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.
Yönetilen XAML uygulamalarında Win2D denetimleri kullanılırken, bu denetimlerin çöp toplayıcı tarafından geri kazanılmasını engelleyebilecek referans sayısı döngüleri önlenmelidir.
Sorununuz varsa...
- Win2D'i C# gibi bir .NET dilinden kullanıyorsunuz (yerel C++değil)
- Win2D XAML denetimlerinden birini kullanırsınız:
- Win2D denetimi olaylarına abone olursunuz (örneğin
Draw, ,CreateResourcesSizeChanged...) - Uygulamanız birden fazla XAML sayfası arasında ileri geri hareket eder
Tüm bu koşullar karşılanırsa, başvuru sayısı döngüsü Win2D denetiminin çöp toplama işlemine tabi tutulmamasını sağlar. Uygulama her farklı bir sayfaya taşındığında yeni Win2D kaynakları ayrılır, ancak eski kaynaklar hiçbir zaman serbest bırakılmaz, bu yüzden bellek sızıntısı olur. Bunu önlemek için, döngüyü açıkça kesmek için kod eklemeniz gerekir.
Düzeltme adımları
Referans sayısı döngüsünü kesmek ve sayfanızın çöp toplanmasına izin vermek için:
-
UnloadedWin2D denetimini içeren XAML sayfasının olayını bağlama -
Unloadedişleyicisinde Win2D denetimindeRemoveFromVisualTreeçağrısı yapılır -
Unloadedişleyicisinde, Win2D denetimine yapılan tüm açık başvurularınullolarak ayarlayarak serbest bırakın.
Örnek kod:
void page_Unloaded(object sender, RoutedEventArgs e)
{
this.canvas.RemoveFromVisualTree();
this.canvas = null;
}
Çalışan örnekler için Örnek Galeri tanıtım sayfalarından herhangi birine bakın.
Döngü sızıntılarını nasıl test edersiniz?
Uygulamanızın refcount döngülerini doğru şekilde bozup bozmadığını test etmek için Win2D denetimleri içeren tüm XAML sayfalarına sonlandırıcı yöntemi ekleyin:
~MyPage()
{
System.Diagnostics.Debug.WriteLine("~" + GetType().Name);
}
Oluşturucunuzda App , atık toplamanın düzenli aralıklarla gerçekleşmesini sağlayacak bir zamanlayıcı ayarlayın:
var gcTimer = new DispatcherTimer();
gcTimer.Tick += (sender, e) => { GC.Collect(); };
gcTimer.Interval = TimeSpan.FromSeconds(1);
gcTimer.Start();
Sayfaya gidip, sonra başka bir sayfaya geçin. Tüm döngüler kırıldıysa, Debug.WriteLine çıkışını bir veya iki saniye içinde Visual Studio çıkış bölmesinde görürsünüz.
Çağrının GC.Collect kesintiye neden olduğunu ve performansa zarar verdiğini unutmayın, bu nedenle sızıntı testlerini tamamlar bitirmez bu test kodunu kaldırmanız gerekir!
Kanlı ayrıntılar
Döngü, A nesnesinin B'ye başvurusu olduğunda ve B'nin de A'ya başvurusu olduğunda gerçekleşir. Ya da A B'ye, B C'ye, C ise A'ya vb. başvuruda bulunursa.
Bir XAML denetiminin olaylarına abone olurken, bu tür bir döngü neredeyse kaçınılmazdır:
- XAML sayfası, içinde yer alan tüm denetimlere başvurular içerir
- Denetimler, olaylarına abone olan işleyici temsilcilerine referanslar tutar.
- Her temsilci, hedef örneğine bir başvuru barındırıyor
- Olay işleyicileri genellikle XAML sayfa sınıfının örnek yöntemleridir, bu nedenle hedef örnek başvuruları XAML sayfasına geri dönüp bir döngü oluşturur
İlgili tüm nesneler .NET'te uygulanıyorsa, .NET atık toplama olduğundan ve atık toplama algoritması bir döngüde bağlı olsalar bile nesne gruplarını tanımlayıp geri kazanabildiğinden bu tür döngüler sorun oluşturmaz.
.NET'in aksine, C++, nesnelerin döngülerini algılayamayan ve geri kazanamayan başvuru sayımına göre belleği yönetir. Bu sınırlamaya rağmen, Win2D kullanan C++ uygulamalarının hiçbir sorunu yoktur çünkü C++ olay işleyicileri varsayılan olarak hedef örneğine güçlü referanslar yerine zayıf referanslar tutar. Bu nedenle, sayfa denetime başvurur ve denetim olay işleyicisi temsilcisine başvurur, ancak bu temsilci sayfaya geri başvurmaz, bu nedenle döngü yoktur.
Sorun, Win2D gibi bir C++ WinRT bileşeni bir .NET uygulaması tarafından kullanıldığında ortaya çıkar:
- XAML sayfası uygulamanın bir parçasıdır, bu nedenle çöp toplamayı kullanır
- Win2D denetimi C++ dilinde uygulandığından, başvuru sayımını kullanır
- Olay işleyici temsilcisi, uygulamanın bir parçasıdır; bu nedenle çöp toplama mekanizmasını kullanır ve hedef örnekle güçlü bir referans oluşturur.
Bir döngü var, ancak bu döngüye katılan Win2D nesneleri .NET çöp toplama kullanmıyor. Bu, atık toplayıcının zincirin tamamını göremediğini, bu nedenle nesneleri algılayamayacağı veya geri kazanamadığı anlamına gelir. Bu durum oluştuğunda, uygulamanın döngüyü açıkça kırarak yardımcı olması gerekir. Bu, ya sayfadan denetime yapılan tüm bağlantıları keserek (yukarıda önerildiği gibi) ya da denetimden sayfaya geri dönebilecek olay işleyici temsilcilerine yapılan bütün bağlantıları kaldırarak (tüm olay işleyicilerinden aboneliği sonlandırmak için sayfanın Kaldırıldı olayı kullanılarak) yapılabilir.
Windows developer