Task <int> nasıl int olur?


116

Bu yönteme sahibiz:

async Task<int> AccessTheWebAsync()
{ 
    HttpClient client = new HttpClient();

   Task<string> getStringTask = client.GetStringAsync("http://msdn.microsoft.com");

   // You can do work here that doesn't rely on the string from GetStringAsync.
   DoIndependentWork();

   string urlContents = await getStringTask;
   //The thing is that this returns an int to a method that has a return type of Task<int>
   return urlContents.Length;
}

Task<int>Ve arasında örtük bir dönüşüm gerçekleşir intmi? Değilse, ne oluyor? Çalışmak için nasıl uygulanır?


1
Okumaya devam edin . Derleyicinin bunu asyncanahtar kelimeye göre hallettiğini varsayıyorum .
D Stanley

1
@Freeman, Şu harika açıklamaya bakın: stackoverflow.com/a/4047607/280758
qehgt

Yanıtlar:


171

Task <> ve int arasında örtük bir dönüşüm gerçekleşiyor mu?

Hayır! Bu sadece nasıl async/ awaitçalıştığının bir parçası .

Aşağıdaki gibi asyncbir dönüş türü olması gerektiği bildirilen herhangi bir yöntem :

  • void (mümkünse kaçının)
  • Task (tamamlanma / başarısızlık bildirimi dışında sonuç yok)
  • Task<T>( Tzaman uyumsuz bir şekilde türün mantıksal bir sonucu için )

Derleyici tüm uygun sarmalamayı yapar. Önemli olan, eşzamansız olarak geri döndüğünüzdür urlContents.Length- intgerçek yöntem, awaithenüz tamamlanmamış olan ilk ifadeye ulaştığında geri döneceğinden , yöntemi yalnızca geri döndüremezsiniz . Bunun yerine, Task<int>zaman uyumsuz yöntemin kendisi tamamlandığında tamamlanacak olan bir döndürür .

Not awaittersini yapar - bu unwraps bir Task<T>a Tbu hat işliyor değeri:

string urlContents = await getStringTask;

... ama tabii ki eşzamansız olarak açıyor, oysa sadece kullanmak Resultgörev tamamlanana kadar engelleyecektir. ( awaitBeklenebilir modeli uygulayan diğer türleri açabilirsiniz, ancak Task<T>en sık kullandığınız türdür .)

Bu ikili sarma / sarmalama, eşzamansızın bu kadar birleştirilebilir olmasını sağlayan şeydir. Örneğin, sizinkini çağıran ve sonucu ikiye katlayan başka bir zaman uyumsuz yöntem yazabilirim:

public async Task<int> AccessTheWebAndDoubleAsync()
{
    var task = AccessTheWebAsync();
    int result = await task;
    return result * 2;
}

(Ya da sadece return await AccessTheWebAsync() * 2;elbette.)


3
Kaputun altında nasıl çalıştığına dair herhangi bir ayrıntı sunulabilir mi, sadece merak.
Freeman

8
+1 Her zamanki gibi iyi yanıt. Ve neden bu kadar hızlı yazıyorsun ?!
Felix K.

9
1: Sadece içine bakarak başladı async/ awaitve ben bu son derece sezgisel olmayan bulabilirsiniz. IMO, bir anahtar sözcük veya benzeri olmalıdır returnbu saydam, örneğin yapmak için return async result;(aynı şekilde o await result"unwraps" Tdan Tast<T>).
dav_i

2
@JonSkeet Ama olmadan mantıklı değil await- ile T foo = someTaskT;olsun istiyorum "dolaylı türünü dönüştürülemez Task<T>için T" - Ben ters (sarma içinde bir anahtar kelime olması daha mantıklı olacağını iddia aynı şekilde Task<T>). Ben tamamen kabartmaktan yanayım ama bu durumda asyncyöntemler içinde gereksiz bir şaşkınlık sağladığını düşünüyorum . (Açıkçası konu tartışmalı çünkü zaten konuşulan / kodlanan güçler!)
dav_i

2
@dav_i: Ödev bir anlam ifade etmiyor ama gerisi anlamıyor. Ve yararlı olmasa da, tüm ifadenin mantıklı olduğu durumlar vardır. Yöntemin zaten açıklandığı göz önüne alındığında async, bunun yeterli olduğunu düşünüyorum.
Jon Skeet

18

Task'ı int'e dönüştürmeye gerek yok. Sadece Görev Sonucunu Kullanın.

int taskResult = AccessTheWebAndDouble().Result;

public async Task<int> AccessTheWebAndDouble()
{
    int task = AccessTheWeb();
    return task;
}

Varsa değeri döndürecektir, aksi takdirde 0 döndürür.


20
istediğim bu değil.
Freeman

16
Bu soruya cevap vermiyor. Ama daha da önemlisi, bu çok kötü bir tavsiye . Neredeyse hiç kullanmamalısınız Result; kilitlenmelere neden olabilir! Örneğin şu iş akışını düşünün: (1) "Çimleri biç" yazan bir not yazın. (2) Çimlerin biçilmesini bekleyin (3) Bir sandviç yiyin, (4) Notta ne yazıyorsa yapın ". Bu iş akışıyla, asla bir sandviç yemeyin veya çimleri biçmeyin, çünkü 2. adım senkronize bir beklemedir gelecekte yapacağınız bir şey üzerine . Ama burada tarif ettiğiniz iş akışı bu.
Eric Lippert

@EricLippert: Örneğinizi netleştirmeyin. Beklemenin olmayacağı zaman Sonuç'un nasıl kilitlenmeler getirebileceğini açıklayabilir misiniz?
CharithJ

3
Beklemek, sonucu beklerken bir şeyler yapmak anlamına gelir ve bir şey sonucu hesaplamak için çalışmayı içerebilir. Ancak eşzamanlı beklemeler, siz beklerken hiçbir şey yapmaz, bu da işin yapılmasını engelleyebileceğiniz anlamına gelir.
Eric Lippert

1
@EricLippert. Bunda da aynı sorun olacak mı? 'Task.Run (() => AccessTheWebAndDouble ()). Sonuç;'
CharithJ
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.