Bir yöntem adında "Async" sonekinin kullanımı, "zaman uyumsuz" değiştiricisinin kullanılıp kullanılmadığına bağlı mı?


107

Yöntem adlarının "Async" ile son eklenmesi için kural nedir?

"Async" soneki yalnızcaasync değiştiriciyle bildirilen bir yönteme eklenmeli mi?

public async Task<bool> ConnectAsync()

Yoksa yöntem sadece döner yeterli mi Task<T>yoksa Task?

public Task<bool> ConnectAsync()

4
Adlandırma bölümü için, TAP dokümanı şunu söyler: TAP'deki zaman uyumsuz yöntemler, işlem adından sonra Zaman uyumsuz sonekini içerir; örneğin, bir alma işlemi için GetAsync. Zaman uyumsuz son ekiyle bu yöntem adını zaten içeren bir sınıfa bir TAP yöntemi ekliyorsanız, bunun yerine TaskAsync sonekini kullanın. Örneğin, sınıfta zaten bir GetAsync yöntemi varsa, GetTaskAsync adını kullanın.
James Manning

4
tamam, sanırım "Eşzamansız yöntemler için adlandırma kuralı" sorusunun başlığıyla kafam karıştı
James Manning

1
Bu kötü yapılandırılmış bir sorudur. Tartışan insanlar, belirsiz cevaplar.
Luke Puplett

4
Çünkü birçok insan onu yanlış anladı ve sorulan asıl şey hakkında tartışıyorlar, bunun iki parçalı bir soru olup olmadığını merak ediyorlar. Kafasının karışmasının kanıtı, insanların kafalarının karışık olmasıdır.
Luke Puplett

2
@DavidRR Bu güne kadar, bu sorunun görünüşte neden olduğu kafa karışıklığının miktarını hala anlamıyorum. Düzenlemeleriniz kafa karışıklığında size yardımcı olacak ve muhtemelen başkalarına da yardımcı olacak bir düzen getirdiyse, orijinal formülasyonda başaramadığım bir şeyi başardığınız için düzenlemelerinizi memnuniyetle karşılıyorum. Soru şimdi o kadar eski ki, burada sorduğumda zihniyetimi neredeyse hatırlayamıyorum ve bu yüzden asıl amaç daha az önemli. Luke'un cevabı, hepsinin kafasının karışmadığını yansıtıyor. Son derece yararlı buldum.
kasperhj

Yanıtlar:


128

Microsoft belgelerinde bile gerçeğin belirsiz olduğunu düşünüyorum:

Visual Studio 2012 ve .NET Framework 4.5 ile atfedilir herhangi yöntemde async(anahtar kelime AsyncVisual Basic) bir asenkron metot olarak kabul ve C # ve Visual Basic derleyiciler gerekli dönüşümleri TAP kullanarak zaman uyumsuz yöntemini uygulamak yerine edilmektedir. Zaman uyumsuz bir yöntem, bir Taskveya bir Task<TResult>nesne döndürmelidir .

http://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx

Bu zaten doğru değil. İle herhangi bir yöntem asynceşzamansızdır ve sonra bir Taskveya Task<T>- döndürmesi gerektiğini söyler - bu, bir çağrı yığınının üstündeki yöntemler için doğru değildir, örneğin Button_Click, veya async void.

Elbette, kongrenin amacının ne olduğunu düşünmek zorundasın?

Bunu söyleyebiliriz Asynceki kongre yöntemi awaitable olan API kullanıcıya iletişim kurmaktır. Bir yöntemin beklenebilir olması Taskiçin, bir boşluk Task<T>için veya bir değer döndürme yöntemi için geri dönmesi gerekir ; bu, yalnızca ikincisine son eklenebileceği anlamına gelir Async.

Veya Asyncsonek kuralının, yöntemin hemen geri dönebileceğini, diğer işleri yapmak için mevcut iş parçacığını bırakıp potansiyel olarak yarışlara neden olabileceğini bildirmek olduğunu söyleyebilirsiniz .

Bu Microsoft doc alıntı diyor ki:

Kural olarak, Zaman uyumsuz veya zaman uyumsuz değiştiriciye sahip yöntemlerin adlarına "Zaman uyumsuz" eklersiniz.

http://msdn.microsoft.com/en-us/library/hh191443.aspx#BKMK_NamingConvention

Bu, kendi asenkron yöntemlerin geri dönen son eke Taskihtiyaç duyduğundan bahsetmiyor bile Async, sanırım hepimiz bunu yaptıklarında hemfikiriz.


Yani bu sorunun cevabı şunlar olabilir: ikisi de. Her iki durumda da, anahtar kelimeli Asyncyöntemlere eklemeniz gerekir asyncve bu dönüş Taskveya Task<T>.


Stephen Toub'dan durumu açıklamasını isteyeceğim.

Güncelleme

Ben de yaptım. Ve işte iyi adamımızın yazdığı:

Genel bir yöntem Görev döndürüyorsa ve doğası gereği zaman uyumsuzsa (her zaman tamamlanana kadar eşzamanlı olarak yürütüldüğü bilinen ancak yine de herhangi bir nedenle bir Görev döndüren bir yöntemin aksine), bir "Zaman uyumsuz" sonekine sahip olmalıdır. Kılavuz budur. Buradaki adlandırma ile birincil amaç, bir tüketiciye, çağrılan yöntemin muhtemelen tüm çalışmasını eşzamanlı olarak tamamlamayacağını çok açık hale getirmektir; elbette, işlevselliğin hem eşzamanlı hem de eşzamansız yöntemlerle ortaya çıktığı durumda, onları ayırt etmek için bir ad farkına ihtiyaç duyduğunuzda yardımcı olur. Yöntemin zaman uyumsuz uygulamasını nasıl başardığı, adlandırma için önemsizdir: derleyicinin yardımını toplamak için zaman uyumsuz / beklemenin kullanılıp kullanılmadığı veya System.Threading.Tasks'ten türlerin ve yöntemlerin doğrudan kullanılıp kullanılmadığı (örn. g. TaskCompletionSource), yöntemin tüketicisi söz konusu olduğunda yöntemin imzasını etkilemediği için gerçekten önemli değildir.

Tabii ki, bir kılavuzun her zaman istisnaları vardır. Adlandırma durumunda en dikkate değer olanı, tüm bir türün varoluş nedeninin eşzamansız odaklı işlevsellik sağlamak olduğu durumlar olacaktır; bu durumda, her yöntemde Async'e sahip olmak aşırı olacaktır, örneğin, diğer Görevleri üreten Görevin kendisindeki yöntemler .

Boşluk geri dönüşlü eşzamansız yöntemlere gelince, arayan kişinin eşzamansız çalışmanın ne zaman tamamlandığını bilmesinin iyi bir yolu olmadığından, bunların kamuya açık yüzey alanında olması arzu edilmez. Boşluk döndüren bir eşzamansız yöntemi herkese açık olarak ifşa etmeniz gerekiyorsa, büyük olasılıkla eşzamansız çalışmanın başlatıldığını bildiren bir ada sahip olmak istersiniz ve mantıklıysa burada "Eşzamansız" sonekini kullanabilirsiniz. Bu davanın ne kadar nadir olması gerektiği göz önüne alındığında, bunun gerçekten duruma göre bir karar olduğunu düşünüyorum.

Umarım yardımcı olur Steve

Stephen'ın açılış cümlesindeki kısa ve öz rehber yeterince açık. Hariç tutuyor async voidçünkü böyle bir tasarıma sahip genel bir API yaratmak istemenin olağandışı bir durumdur çünkü zaman uyumsuz bir boşluğu uygulamanın doğru yolu düz bir Taskörnek döndürmek ve derleyicinin büyüsüne izin vermektir. Ancak, eğer a public async voidistediyseniz, o zaman eklemeniz Asyncönerilir. async voidOlay işleyicileri gibi diğer yığın üstü yöntemler genellikle herkese açık değildir ve önemli değildir / nitelendirilmez.

Benim için kendimi son eklemeli merak bulursanız söylüyor Asyncbir de async void, muhtemelen bir çevirmek gerekir async Tasksonra ekleme arayanlar bunu bekliyor böylece Async.


20
Yöntem çağrıları için derleme zamanı kontrollerinin olmaması çok yazık .. oh bekle. Yöntemi Get veya GetAsync olarak adlandırırsam ve çağıran taraftan await kullanmazsam , derleme oluşturulamaz. Bu nedenle bu kural SILLY ve gerçekten birçok Microsoft Stil yönergesine aykırıdır, örneğin PersonStringveya PriceDecimalneden kullanılmaması gibi şeylerden kaçınmak gibi GetAsync- zaman uyumsuz API'lerin API tüketicilerinin bu konuda endişelenmelerine gerek yoktur, çünkü istek yine de tüm görevler tamamlandıktan sonra her zaman geri döner. Aptalca ve gerçekten canımı sıkıyor. Ama bu, kimsenin neden orada olduğunu bilmediği başka bir kongre.
Piotr Kula

2
@ppumkin: Stephen'ın belirttiği gibi, bir yöntem async / await kullanmadan doğası gereği kolayca asenkronize olabilir, bu nedenle arayanın, işlevin asenkron çalışıp çalışmadığının adından başka bir göstergesi yoktur.
Hannobo

6
@ppumkin: Zaman uyumsuz bir yöntemin beklenememesi, varsayılan olarak derleme zamanı uyarısıyla sonuçlanır; bir yapı hatası değil.
Dustin Cleveland

7
Bu kongreyi aptalca buluyorum. Bir yöntemin eşzamansız olduğuna dair üç otomatik gösterge vardır: 1. Dönüş türü Görev'tir. 2. Kod tamamlama, beklenebilir bir ipucu sunar 3. IDE, yeşil renkle altını çizerek ve bir derleyici uyarısı sunarak sizi uyaracaktır. Bu yüzden @ppumkin'e tamamen katılıyorum. Eşzamansız son eki, böyle bir özellik yazmışsınız gibi saçmadır: public Lazy <Customer> CustomerLazy. Bunu kim yapacak! ??
Marco

2
@Marco Bu fikri GitHub'da gündeme getirdim, buranın en iyi yer olduğunu düşündüm, ancak alacağımı düşündüğüm etkileşimde değilim: github.com/dotnet/core/issues/1464
Luke Puplett

68

Kodumun çoğunun eşzamansız olarak çalıştığı diğer sistemleri çağıran çok sayıda API hizmetleri ve başka uygulamalar oluşturuyorum.

Takip ettiğim kendi genel kuralım:

Aynı şeyi döndüren hem eşzamansız hem de zaman uyumsuz yöntem varsa, zaman uyumsuz olanı Zaman uyumsuz olana eklerim. Aksi takdirde değil.

Örnekler:

Yalnızca bir yöntem:

public async Task<User> GetUser() { [...] }

İki imzayla aynı yöntem:

public User GetUser() { [...] }

public async Task<User> GetUserAsync() { [...] }

Bu mantıklıdır, çünkü döndürülen verilerle aynıdır, ancak farklı olan tek şey verilerin kendisi değil, verilerin döndürülme şeklidir .

Ayrıca, bu adlandırma kurallarının, zaman uyumsuz yöntemler sunma ve hala geriye dönük uyumluluğu sürdürme ihtiyacı nedeniyle var olduğunu düşünüyorum.

Yeni kodun Async sonekini kullanmaması gerektiğini savunuyorum. Bu iş parçacığında daha önce belirtildiği gibi String veya Int türünün dönüş türü kadar açıktır.


8
Katılıyorum, özellikle de genellikle 'tüm yol boyunca eşzamansız' gitmeniz gerektiğine katılıyorum, bu durumda son ek gereksizdir - kodun% 90'ına eklemenin amacı nedir;)
Bartosz

3
bu en iyi çözümdür. Farkında olmadan, API'lerimde de aynı şekilde yapıyorum.
Marco

2
Bu, eşzamansız uygulamanın tüm yöntemleriyle "
Eşzamansız" son ekinden

Bu teknikle ilgili sorun, daha sonra eşzamansız olmayan bir sürüm oluşturursanız, aksi takdirde tercih ettiğiniz "GetUser ()" adını kullanamayacağınızdır.
David

3
Bu, gitmenin pragmatik yoludur. Zaman uyumsuz değiştiriciye sahip her yönteme Async eklemek yalnızca Hungarian Notation 2019'dur. @David, daha sonra eşzamansız olmayan bir sürüm eklerseniz, yöntemleri yeniden adlandırın ve adlandırma kuralını izleyin veya bunu yapmayın.
Skrymsli

25

Yöntem adlarının "Async" ile son eklenmesi için kural nedir.

Görev tabanlı zaman uyumsuz Desen (TAP) yöntemleri her zaman döndürmesi gerektiğini dikte Task<T>(veya Task) ve ile adlandırılacak zaman uyumsuz soneki; bu kullanımdan ayrıdır async. Hem Task<bool> Connect()ve derlemek ve sadece iyi çalıştırmak, ancak TAP adlandırma kuralı aşağıdaki olmayacaktır olacaktır.asyncTask<bool> Connect()

Yöntem asyncdeğiştiriciyi içermeli mi yoksa sadece Task'ı döndürmesi için yeterli mi?

Yöntemin gövdesi (dönüş türü veya adı ne olursa olsun) içeriyorsa await, kullanmanız gerekirasync ; ve derleyici size "'await' operatörü yalnızca zaman uyumsuz bir yöntem içinde kullanılabilir. ..." diyecektir. Geri dönmek Task<T>veya Taskkullanmaktan kaçınmak için "yeterli" değil async. Ayrıntılar için eşzamansız (C # Başvurusu) bölümüne bakın .

Yani bu imzalardan hangisi doğru:

Her ikisi de ve TAP kurallarına uygun şekilde uyun. Her zaman anahtar sözcüğü kullanabilirsiniz , ancak "Bu eşzamansız yöntem 'bekleme' işleçlerinden yoksundur ve gövde kullanmıyorsa eşzamanlı olarak çalışır. ..." şeklinde bir derleyici uyarısı alırsınız .asyncTask<bool> ConnectAsync()Task<bool> ConnectAsync()asyncawait


1
asyncAnahtar kelimeyi kullanıp kullanmamanıza değil, yöntem adına "Zaman uyumsuz" ekleyip eklemediğinizi ifade ediyor .
2013

1
@ Anahtar kelimeyi kullanıp kullanmamak asyncsorunun ikinci kısmıdır.
Corak

2
@Servy İki parçalı bir sorudur. İlk kısım, sizin de söylediğiniz gibi yöntem adına "Async" eklenip eklenmeyeceğidir. İkinci kısım, asyncdeğiştiricinin kullanılıp kullanılmayacağıdır . Ayrıca bkz. OP örnekleri, public async Task<bool> ConnectAsync()( asyncdeğiştiricili) vs public Task<bool> ConnectAsync()( asyncdeğiştiricisiz). Her iki durumda da yöntem adının kendisi "Async" sonekine sahiptir.
Corak

2
Öyle değil iki parçalı bir soru. Buradaki soru, dönen yöntemlerin yöntem adlarına Taskveya sahip olan yöntemlere "Async" eklenmeli mi async Task?
kasperhj

3
@lejon: soruyu geliştirmelisiniz; "vs." kod parçacıkları, sorunun (bütünüyle) eşzamansız olduğunu açıkça ortaya koyuyor çünkü tek fark bu.
2013

11

yoksa sadece Task'ı döndürmesi yeterli mi?

Bu. asyncBuradaki anahtar kelime asıl mesele değildir. Eşzamansızlığı asyncanahtar sözcüğü kullanmadan uygularsanız, yöntem genel anlamda hala " Eşzamansız " olur.


7

Yana Taskve Task<T>her ikisi awaitable tipleridir, temsil ettikleri bazı zaman uyumsuz işlem. Ya da en azından temsil etmeleri gerekir.

AsyncBazı durumlarda (tümü değil) bir değer döndürmeyen, bunun yerine devam eden bir işlemin etrafında bir sarmalayıcı döndüren bir yönteme sonek eklemelisiniz . Bu sarmalayıcı genellikle bir Task, ancak Windows RT'de olabilir IAsyncInfo. İçgüdülerinizi takip edin ve kodunuzun bir kullanıcısı Asyncişlevi görürse , o yöntemin çağrılmasının o yöntemin sonucundan ayrıldığını ve buna göre hareket etmeleri gerektiğini bileceğini unutmayın.

Dönen Task.Delayve Task.WhenAlldönen gibi yöntemler olduğunu Taskve henüz Asyncsonekin olmadığını unutmayın .

Ayrıca ateşiasync void temsil eden ve asenkron metodu unutan metotlar olduğunu ve metodun bu şekilde inşa edildiğini bilmelisiniz.


6

Yöntemin asyncdeğiştiriciyle bildirilip bildirilmediğine bakılmaksızın bir Task döndürürse Async sonekini kullanması gerektiğini iddia ediyorum .

Bunun arkasındaki sebep, ismin arayüzde beyan edilmesidir. Arayüz, bir dönüş türü olan bir Task. Sonra bu arayüzün iki uygulaması vardır, bir uygulama asyncdeğiştiriciyi kullanarak onu uygular , diğeri yapmaz.

public interface IFoo
{
    Task FooAsync();
}

public class FooA : IFoo
{
    public Task FooAsync() { /* ... */ }
}

public class FooB : IFoo
{
    public async Task FooAsync() { /* ... */ }
}

Bu çok doğru. Her zaman her yerde arabirimler kullanırız ve arabirimler eşzamansız olarak ilan edilemez. Bu nedenle, Async son ekini kullanma konusundaki resmi kılavuzlar bana tamamen saçma görünüyor. Async anahtar kelimesinin sadece bir uygulama ayrıntısı, yöntemin iç bileşenlerinin bir parçası olduğunu ve adını veya harici herhangi bir şeyi etkilememesi gerektiğini düşünüyorum.
Al Kepp

5

Gelen zaman uyumsuz ve asenkron programlama burada bekliyor (C #) , Microsoft aşağıdaki rehberlik sunmaktadır:

Adlandırma kuralı

Kural olarak, zaman uyumsuz değiştiriciye sahip yöntemlerin adlarına "Zaman uyumsuz" eklersiniz .

Bir olayın, temel sınıfın veya arabirim sözleşmesinin farklı bir ad önerdiği kuralı yok sayabilirsiniz. Örneğin, gibi genel olay işleyicilerini yeniden adlandırmamalısınız Button1_Click.

Bu kılavuzu eksik ve tatmin edici bulmuyorum. Bu, asyncdeğiştiricinin yokluğunda Connectbunun yerine bu yöntemin adlandırılması gerektiği anlamına mı geliyor ConnectAsync?

public Task<bool> ConnectAsync()
{
    return ConnectAsyncInternal();
}

Ben öyle düşünmüyorum. Belirtildiği gibi özlü cevap tarafından @Servy ve daha ayrıntılı cevap tarafından @Luke Puplett , Ben yöntem, uygun ve gerçekten de beklenen olduğuna inanıyoruz gerekir adlandırılacak ConnectAsync(bir awaitable döndürdüğü için). Bu daha da desteklenmesi kapsamında, @John Skeet içinde bu cevap başka soruya ekler Asyncbakılmaksızın varlığı yöntemi adının asyncdeğiştirici.

Son olarak, başka bir soruda , @Damien_The_Unbeliever tarafından yazılan bu yorumu düşünün :

async/awaityöntemlerinizin uygulama ayrıntılarıdır. Arayanlar söz konusu olduğu sürece, yönteminizin beyan edilmiş olması async Task Method()veya sadece tek bir not bile önemli değildir . (Aslında, bu ikisi arasında daha sonraki bir noktada, bir kırılma değişikliği olarak kabul edilmeden geçiş yapmakta özgürsünüz.)Task Method()

Bundan, nasıl adlandırılması gerektiğini belirleyen şeyin , yöntemin asenkron doğası olduğu sonucuna varıyorum . Yöntemin kullanıcısı, asyncdeğiştiricinin uygulamasında kullanılıp kullanılmadığını bile bilmeyecektir (C # kaynak kodu veya CIL olmadan).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.