Sorun, Tasksonuç üretme amaçlı olmayan , genel olmayan sınıfı kullanmanızdır . Dolayısıyla, zaman Taskuyumsuz bir temsilci geçirerek örneği oluşturduğunuzda :
Task myTask = new Task(async () =>
... delege muamelesi görüyor async void. An async voidbir 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 Startdış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 Unwrapdış 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 Unwrapgü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, myTaskdeğ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 Taskgöz ardı edilmeyeceği anlamına gelir ). Bu yöntemin bir kabul ettiği talihsiz durumda, Actiondelege olarak kabul edilecektir async void. Bu nadiren istediğiniz şeydir.