Sorun, Task
sonuç üretme amaçlı olmayan , genel olmayan sınıfı kullanmanızdır . Dolayısıyla, zaman Task
uyumsuz bir temsilci geçirerek örneği oluşturduğunuzda :
Task myTask = new Task(async () =>
... delege muamelesi görüyor async void
. An async void
bir değil Task
, beklenemez, istisnası ele alınamaz ve StackOverflow'da ve başka yerlerde sinirli programcılar tarafından yapılan binlerce sorunun kaynağıdır . Çözüm, genel Task<TResult>
sınıfı kullanmaktır , çünkü bir sonuç döndürmek istiyorsunuz ve sonuç başka bir sonuçtur Task
. Yani aşağıdakileri oluşturmanız gerekir Task<Task>
:
Task<Task> myTask = new Task<Task>(async () =>
Şimdi Start
dışta Task<Task>
olduğunuzda neredeyse anında tamamlanacak çünkü işi sadece iç kısmı yaratmaktır Task
. O zaman içini de beklemeniz gerekecek Task
. Bu şekilde yapılabilir:
myTask.Start();
Task myInnerTask = await myTask;
await myInnerTask;
İki alternatifiniz var. İç kısım için açık bir referansa ihtiyacınız yoksa Task
, dış kısmı Task<Task>
iki kez bekleyebilirsiniz :
await await myTask;
... veya Unwrap
dış ve iç görevleri bir araya getiren dahili uzantı yöntemini kullanabilirsiniz :
await myTask.Unwrap();
Bu kaydırma Task.Run
, sıcak görevler oluşturan çok daha popüler yöntemi kullandığınızda otomatik olarak gerçekleşir , bu nedenle Unwrap
günümüzde çok sık kullanılmaz.
Zaman uyumsuz temsilcinizin bir sonuç, örneğin a sonucu döndürmesi gerektiğine karar verirseniz string
, myTask
değişkeni tür olarak bildirmeniz gerekir Task<Task<string>>
.
Not:Task
Soğuk görevler oluşturmak için kurucuların kullanımını onaylamıyorum. Bir uygulama genellikle kaşlarını çattığından, gerçekten bilmiyorum nedenlerle, ama muhtemelen o kadar nadiren kullanıldığı için, diğer habersiz kullanıcıları / koruyucular / gözden geçirenleri kodu şaşırtıcı bir şekilde yakalama potansiyeline sahiptir.
Genel öneri: Bir yönteme argüman olarak zaman uyumsuz delege verirken dikkatli olun. Bu yöntem ideal olarak bir Func<Task>
argüman (zaman uyumsuz delegeleri anlayan anlamına gelir) veya en azından bir Func<T>
argüman beklemelidir (en azından üretilenin Task
göz ardı edilmeyeceği anlamına gelir ). Bu yöntemin bir kabul ettiği talihsiz durumda, Action
delege olarak kabul edilecektir async void
. Bu nadiren istediğiniz şeydir.