Baru saja mendapat VS2012 dan mencoba menangani async
.
Katakanlah saya punya metode yang mengambil beberapa nilai dari sumber pemblokiran. Saya tidak ingin penelepon metode untuk memblokir. Saya bisa menulis metode untuk mengambil callback yang dipanggil ketika nilainya tiba, tetapi karena saya menggunakan C # 5, saya memutuskan untuk membuat metode async sehingga penelepon tidak harus berurusan dengan callback:
// contrived example (edited in response to Servy's comment)
public static Task<string> PromptForStringAsync(string prompt)
{
return Task.Factory.StartNew(() => {
Console.Write(prompt);
return Console.ReadLine();
});
}
Inilah contoh metode yang menyebutnya. Jika PromptForStringAsync
tidak async, metode ini akan membutuhkan peneleponan kembali di dalam panggilan balik. Dengan async, saya bisa menulis metode saya dengan cara yang sangat alami ini:
public static async Task GetNameAsync()
{
string firstname = await PromptForStringAsync("Enter your first name: ");
Console.WriteLine("Welcome {0}.", firstname);
string lastname = await PromptForStringAsync("Enter your last name: ");
Console.WriteLine("Name saved as '{0} {1}'.", firstname, lastname);
}
Sejauh ini baik. Masalahnya adalah ketika saya memanggil GetNameAsync:
public static void DoStuff()
{
GetNameAsync();
MainWorkOfApplicationIDontWantBlocked();
}
Intinya GetNameAsync
adalah asinkron. Saya tidak ingin memblokir, karena saya ingin kembali ke MainWorkOfApplicationIDontWantBlocked ASAP dan biarkan GetNameAsync melakukan hal itu di latar belakang. Namun, menyebutnya dengan cara ini memberi saya peringatan kompiler di GetNameAsync
telepon:
Warning 1 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
Saya sangat menyadari bahwa "eksekusi metode saat ini berlanjut sebelum panggilan selesai". Itulah titik kode asynchronous, kan?
Saya lebih suka kode saya dikompilasi tanpa peringatan, tetapi tidak ada yang bisa "diperbaiki" di sini karena kode melakukan apa yang saya inginkan. Saya bisa menghilangkan peringatan dengan menyimpan nilai pengembalian GetNameAsync
:
public static void DoStuff()
{
var result = GetNameAsync(); // supress warning
MainWorkOfApplicationIDontWantBlocked();
}
Tapi sekarang saya punya kode berlebihan. Visual Studio tampaknya mengerti bahwa saya dipaksa untuk menulis kode yang tidak perlu ini, karena menekan peringatan "nilai tidak pernah digunakan" yang normal.
Saya juga bisa menghilangkan peringatan dengan membungkus GetNameAsync dengan metode yang tidak async:
public static Task GetNameWrapper()
{
return GetNameAsync();
}
Tapi itu kode yang lebih berlebihan. Jadi saya harus menulis kode saya tidak perlu atau mentolerir peringatan yang tidak perlu.
Apakah ada sesuatu tentang penggunaan async yang salah di sini?
GetNameAsync
memberikan nama lengkap yang disediakan oleh pengguna (yaitu Task<Name>
, daripada hanya mengembalikan Task
? DoStuff
Lalu dapat menyimpan tugas itu, dan apakah await
itu setelah metode lain, atau bahkan meneruskan tugas ke yang lain metode sehingga bisa await
atau di Wait
suatu tempat di dalam implementasi itu
async
kata kunci.
PromptForStringAsync
Anda melakukan lebih banyak pekerjaan daripada yang Anda butuhkan; kembalikan saja hasilTask.Factory.StartNew
. Sudah tugas siapa yang nilainya adalah string yang dimasukkan di konsol. Tidak perlu menunggu untuk mengembalikan hasilnya; hal itu tidak menambah nilai baru.