Saya sudah mencoba beberapa lama untuk mendapatkan sesuatu yang saya pikir akan mudah bekerja dengan .NET 4.5
Saya ingin menjalankan dua tugas yang berjalan lama pada waktu yang sama dan mengumpulkan
hasilnya dengan cara terbaik C # 4.5 (RTM)
Berikut ini berfungsi tetapi saya tidak menyukainya karena:
- Saya ingin
Sleep
menjadi metode async sehingga bisaawait
metode lain - Itu hanya terlihat kikuk
Task.Run()
- Saya tidak berpikir ini bahkan menggunakan fitur bahasa baru sama sekali!
Kode kerja:
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Task.Run(() => Sleep(5000));
var task2 = Task.Run(() => Sleep(3000));
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}
private static int Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
Console.WriteLine("Sleeping for " + ms + " FINISHED");
return ms;
}
Kode tidak berfungsi:
Pembaruan: Ini benar-benar berfungsi dan merupakan cara yang benar untuk melakukannya, satu-satunya masalah adalah file Thread.Sleep
Kode ini tidak berfungsi karena panggilan untuk Sleep(5000)
segera memulai tugas yang berjalan sehingga Sleep(1000)
tidak berjalan hingga selesai. Hal ini benar meskipun Sleep
adalah async
dan aku tidak menggunakan await
atau menelepon .Result
terlalu cepat.
Saya pikir mungkin ada cara untuk mendapatkan non-running Task<T>
dengan memanggil async
metode sehingga saya kemudian dapat memanggil Start()
dua tugas, tetapi saya tidak tahu bagaimana cara mendapatkan Task<T>
dari memanggil metode async.
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Sleep(5000); // blocks
var task2 = Sleep(1000);
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for " + totalSlept + " ms");
}
private static async Task<int> Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
return ms;
}
sumber
task1.Result
bukanvar task1 = Sleep(5000)
karena metode Sleep Anda tanpa menunggu kata kunci sinkron.Jawaban:
Anda harus menggunakan Task.Delay alih-alih Sleep untuk pemrograman async dan kemudian gunakan Task.WhenAll untuk menggabungkan hasil tugas. Tugas akan berjalan paralel.
sumber
sumber
Go
sinkron, tetapi ingin menyelesaikan dua tugas independen secara asinkron (yaitu tidak perlu menyelesaikan sebelum yang lain, tetapi keduanya harus diselesaikan sebelum eksekusi dilanjutkan) makaTask.WaitAll
akan lebih baik, dan Anda tidak Tidak memerlukan kata kunci await, sehingga tidak memerlukanGo
metode pemanggilan untuk menjadi asinkron itu sendiri. Tidak ada pendekatan yang lebih baik, hanya masalah apa tujuan Anda.async void LongTask1() {...}
kosong : tidak memiliki properti Task.Result. Gunakan Task tanpa T dalam kasus seperti:async Task LongTask1()
.Task<TResult> t1 = LongTask1();
dan sekarang saya mengertit1.Result
.<TResult>
adalah jenis pengembalian hasil Anda. Anda akan memerlukanreturn <TResult>
metode Anda agar ini berfungsi.t1
dant2
variabel, Anda dapat menggunakannew Task(...)
. Sebagai contoh:int int1 = 0; await Task.WhenAll(new Task(async () => { int1 = await LongTask1(); }));
. Satu tangkapan dari pendekatan ini adalah bahwa kompilator tidak akan mengenali bahwa variabel itu ditugaskan dan akan memperlakukannya sebagai tidak ditetapkan jika Anda tidak memberikannya nilai awal.Meskipun
Sleep
metode Anda adalah asinkron,Thread.Sleep
bukan. Ide keseluruhan dari async adalah menggunakan kembali satu utas, bukan memulai banyak utas. Karena Anda telah memblokir menggunakan panggilan sinkron ke Thread.Sleep, itu tidak akan berfungsi.Saya berasumsi bahwa itu
Thread.Sleep
adalah penyederhanaan dari apa yang sebenarnya ingin Anda lakukan. Dapatkah penerapan Anda yang sebenarnya diberi kode sebagai metode asinkron?Jika Anda memang perlu menjalankan beberapa panggilan pemblokiran sinkron, saya pikir mencari di tempat lain!
sumber
var x = y()
dan belumvar x=await y()
atauy().wait()
masih itu tunggu dulu, dan jika async tidak menanganinya dengan sendirinya, apa yang harus saya lakukan? CATATAN bahwa y didekorasi dengan async, dan saya berharap itu melakukan semua dalam waktu semua, tidak tepat di tempat itu ditetapkan, EDIT: saya hanya ketika pasangan saya berkata, mari kita cobaTask.Factory
, dan dia mengatakan itu berhasil ketika saya keluar sisi kelas iniUntuk menjawab poin ini:
Anda mungkin bisa menulis ulang
Sleep
fungsinya seperti ini:menjalankan kode ini akan menghasilkan:
sumber
Sekarang akhir pekan !
sumber
Artikel ini membantu menjelaskan banyak hal. Ini dalam gaya FAQ.
FAQ Async / Await
Bagian ini menjelaskan mengapa
Thread.Sleep
berjalan pada utas asli yang sama - yang menyebabkan kebingungan awal saya.sumber