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.
Not
Bu makale bir özellik belirtimidir. Belirtim, özelliğin tasarım belgesi olarak görev alır. Önerilen belirtim değişikliklerini ve özelliğin tasarımı ve geliştirilmesi sırasında gereken bilgileri içerir. Bu makaleler, önerilen belirtim değişiklikleri son haline getirilene ve geçerli ECMA belirtimine dahil edilene kadar yayımlanır.
Özellik belirtimi ile tamamlanan uygulama arasında bazı tutarsızlıklar olabilir. Bu farklılıklar, ilgilidil tasarım toplantısı (LDM) notlarında yakalanır.
Özellik belirtimlerini C# dil standardına benimseme işlemi hakkında daha fazla bilgi edinmek için belirtimleri makalesinde bulabilirsiniz.
Şampiyon sorunu: https://github.com/dotnet/csharplang/issues/7104
Özet
System.Threading.Lock'in lock anahtar sözcüğüyle nasıl etkileşime girdiğini özel olarak ele al (arka planda EnterScope yönteminin çağrılması).
Mümkün olduğunda türün yanlışlıkla yanlış kullanılmasını önlemek için statik analiz uyarıları ekleyin.
Motivasyon
.NET 9, mevcut monitör tabanlı kilitlemeye daha iyi bir alternatif olarak yeni bir System.Threading.Lock türü sunuyor.
C# dilinde lock anahtar sözcüğü bulunması, geliştiricilerin bunu bu yeni türle kullanabileceklerini düşünmesine neden olabilir.
Bunu yapmak bu türün semantiğine göre kilitlenmez, bunun yerine bunu başka bir nesne olarak ele alır ve monitör tabanlı kilitlemeyi kullanır.
namespace System.Threading
{
public sealed class Lock
{
public void Enter();
public void Exit();
public Scope EnterScope();
public ref struct Scope
{
public void Dispose();
}
}
}
Ayrıntılı tasarım
Kilitleme deyiminin semantiği (§13.13), System.Threading.Lock türü için özel bir duruma göre değiştirilmiştir.
lockşeklinde birlock (x) { ... }deyimi
xSystem.Threading.Locktüründe bir ifade olduğu tam olarak şunun eşdeğeridir:veusing (x.EnterScope()) { ... }System.Threading.Lockaşağıdaki şekle sahip olmalıdır:namespace System.Threading { public sealed class Lock { public Scope EnterScope(); public ref struct Scope { public void Dispose(); } } }- burada
xbir reference_typeifadesidir, tam olarak şunun eşdeğeridir: [...]
Şeklin tam olarak denetlenmeyebileceğini unutmayın (örneğin, Lock türü sealeddeğilse hata veya uyarı olmaz), ancak özellik beklendiği gibi çalışmayabilir (örneğin, özellik türetilmiş tür olmadığını varsaydığından Lock türetilmiş bir türe dönüştürürken hiçbir uyarı olmaz).
Ayrıca, türü yukarı yayınlanırken örtük başvuru dönüştürmelerine (System.Threading.Lock) yeni uyarılar eklenir:
Örtük referans dönüşümleri şunlardır:
- herhangi bir reference_type kadar
objectvedynamic.
- reference_type
System.Threading.Lockolduğu bilindiğinde uyarı verilir.- Herhangi bir class_type
S'dan herhangi bir class_typeT'e,STtüretilmiş olması şartıyla.
SSystem.Threading.Lockolduğu bilindiğinde bir uyarı bildirilir.- Herhangi bir class_type
S'den herhangi bir interface_typeT'ye,ST'yi uyguluyorsa.
SSystem.Threading.Lockolduğu bilindiğinde bir uyarı bildirilir.- [...]
object l = new System.Threading.Lock(); // warning
lock (l) { } // monitor-based locking is used here
Bu uyarının eşdeğer açık dönüştürmelerde bile oluştuğuna dikkat edin.
Derleyici, örnek object'a dönüştürüldükten sonra kilitlenemediğinde bazı durumlarda uyarıyı bildirmekten kaçınır.
- dönüştürme örtük olduğunda ve nesne eşitliği işleci çağırmasının bir parçası olduğunda.
var l = new System.Threading.Lock();
if (l != null) // no warning even though `l` is implicitly converted to `object` for `operator!=(object, object)`
// ...
Uyarıdan kaçmak ve monitör tabanlı kilitleme kullanımını zorlamak için
- genellikle kullanılan uyarı bastırma yöntemleri (
#pragma warning disable), -
MonitorAPI'leri doğrudan -
object AsObject<T>(T l) => (object)l;gibi dolaylı atama.
Alternatif
Diğer türlerin de
lockanahtar sözcüğüyle etkileşime geçmek için kullanabileceği genel bir deseni destekleyin. Bu,ref struct'ler jeneriklere katılabildiğinde uygulanabilecek gelecekteki bir çalışmadır. LDM 2023-12-04üzerinde tartışıldı.Mevcut monitör tabanlı kilitleme ile yeni
Lock(veya gelecekte desen) arasındaki belirsizliği önlemek için şunları yapabiliriz:- Mevcut
lockdeyimini yeniden kullanmak yerine, yeni bir söz dizimi tanıtın. - Yeni kilit türlerinin
structolmasını gerektir (mevcutlockdeğer türlerine izin vermediğinden). Yapıların yavaş başlatması varsa, varsayılan oluşturucular ve kopyalama ile ilgili sorunlar olabilir.
- Mevcut
Kod oluşturma, iş parçacığı iptallerine karşı sağlamlaştırılabilir (ki bunlar da artık kullanılmıyor).
Tür parametresi olarak
Lockgeçirildiğinde de uyarabiliriz çünkü tür parametresinde kilitleme her zaman monitör tabanlı kilitleme kullanır:M(new Lock()); // could warn here void M<T>(T x) // (specifying `where T : Lock` makes no difference) { lock (x) { } // because this uses Monitor }Ancak bu,
Lock'lerin bir listede saklanması sırasında istenmeyen uyarılara neden olur.List<Lock> list = new(); list.Add(new Lock()); // would warn hereSystem.Threading.Lockileusing'lerdeawaitkullanımını önlemek için statik analiz içerebiliriz. Örneğin,using (lockVar.EnterScope()) { await ... }gibi bir kod için ya bir hata ya da bir uyarı verebiliriz. Şu andaLock.Scopebirref structolduğundan bu gerekli değildir, bu nedenle kod yine de geçersizdir. Eğer bir günref structyöntemlerindeasync'lere izin verirsek veyaLock.Scope'yiref structolmayacak şekilde değiştirirsek, bu analiz yararlı hale gelecektir. (Gelecekte uygulanırsa genel desenle eşleşen tüm kilit türlerini de göz önünde bulundurmamız gerekebilir. Bazı kilit türlerininawaitile kullanılmasına izin verilebileceği için bir geri çevirme mekanizması olması gerekebilir.) Alternatif olarak, bu çalışma zamanının bir parçası olarak gönderilen bir çözümleyici olarak uygulanabilir.Değer türlerinin
lockyapılamama kısıtlamasını gevşetebiliriz- yeni
Locktürü için (sadece API teklifi bunuclass'denstruct'ye değiştirdiyse gereklidir) - gelecekte uygulandığında herhangi bir türün katılabileceği genel düzen için.
- yeni
Yeni
lock,asynciçindeawaitkullanılmadığılockyöntemlerinde izin verebiliriz.- Şu anda
lock,usingkaynağı ileref struct'e düşürüldüğünden, bu da derleme sırasında bir hata oluşmasına neden olur. Geçici çözüm,lock'ı ayrı birasyncolmayan metoda çıkarmaktır. -
ref struct Scopekullanmak yerine,Lock.EnterLock.Exittryiçinde / vefinallyyöntemleri yayabiliriz. Ancak,Exityöntemi,Enter'den farklı bir iş parçacığından çağrıldığında mutlaka bir hata atmalıdır; bu nedenleScopekullanıldığında kaçınılan bir iş parçacığı araması içerir. - En iyisi,
usinggövdesinderef structyoksa,async'ınawaitüzerindeki derlenmesineusingyöntemlerinde izin vermektir.
- Şu anda
Tasarım toplantıları
-
LDM 2023-05-01:
lockdeseni desteklemeye ilişkin ilk karar - LDM 2023-10-16: .NET 9 için çalışma kümesine tasnif edildi
-
LDM 2023-12-04: genel desen reddedildi, yalnızca
Locktürüne özel işlem kabul edildi + statik analiz uyarıları eklendi.
C# feature specifications