Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Anda dapat menghindari penyempitan performa dan meningkatkan respons keseluruhan aplikasi Anda dengan menggunakan pemrograman asinkron. Namun, teknik tradisional untuk menulis aplikasi asinkron bisa rumit, membuatnya sulit ditulis, di-debug, dan dipertahankan.
C# mendukung pendekatan yang disederhanakan, pemrograman asinkron, yang memanfaatkan dukungan asinkron dalam runtime .NET. Pengompilasi melakukan pekerjaan sulit yang biasa dilakukan pengembang, dan aplikasi Anda mempertahankan struktur logis yang menyerupai kode sinkron. Akibatnya, Anda mendapatkan semua keuntungan dari pemrograman asinkron dengan sebagian kecil dari upaya.
Topik ini memberikan gambaran umum tentang kapan dan bagaimana menggunakan pemrograman asinkron dan menyertakan tautan ke topik dukungan yang berisi detail dan contoh.
Asinkron meningkatkan responsivitas
Asinkron sangat penting untuk aktivitas yang berpotensi memblokir, seperti akses web. Akses ke sumber daya web terkadang lambat atau tertunda. Jika aktivitas seperti itu diblokir dalam proses sinkron, seluruh aplikasi harus menunggu. Dalam proses asinkron, aplikasi dapat dilanjutkan dengan pekerjaan lain yang tidak bergantung pada sumber daya web sampai tugas yang berpotensi memblokir selesai.
Tabel berikut menunjukkan area umum di mana pemrograman asinkron meningkatkan responsivitas. API yang tercantum dari .NET dan Windows Runtime berisi metode yang mendukung pemrograman asinkron.
Area aplikasi | Jenis .NET dengan metode asinkron | Tipe Windows Runtime dengan metode asinkron |
---|---|---|
Akses web | HttpClient | Windows.Web.Http.HttpClient SyndicationClient |
Bekerja dengan berkas | JsonSerializer StreamReader StreamWriter XmlReader XmlWriter |
StorageFile |
Bekerja dengan gambar | MediaCapture BitmapEncoder BitmapDecoder |
|
Pemrograman WCF | Operasi Sinkron dan Asinkron |
Asinkron terbukti sangat berharga bagi aplikasi yang mengakses utas UI karena semua aktivitas terkait UI biasanya berbagi satu utas. Jika ada proses yang diblokir dalam aplikasi sinkron, semua diblokir. Aplikasi Anda berhenti merespons, dan Anda mungkin menyimpulkan bahwa aplikasi tersebut gagal, padahal sebenarnya hanya sedang menunggu.
Saat Anda menggunakan metode asinkron, aplikasi terus merespons UI. Anda dapat mengubah ukuran atau meminimalkan jendela, misalnya, atau Anda dapat menutup aplikasi jika Anda tidak ingin menunggunya selesai.
Pendekatan berbasis asinkron menambahkan transmisi otomatis yang setara dengan daftar opsi yang dapat Anda pilih saat merancang operasi asinkron. Artinya, Anda mendapatkan semua manfaat pemrograman asinkron tradisional tetapi dengan upaya yang jauh lebih sedikit dari pengembang.
Metode asinkron mudah ditulis
Asinkron dan menunggu kata kunci di C# adalah inti dari pemrograman asinkron. Dengan menggunakan kedua kata kunci tersebut, Anda dapat menggunakan sumber daya dalam .NET Framework, .NET Core, atau Windows Runtime untuk membuat metode asinkron hampir semampu Anda membuat metode sinkron. Metode asinkron yang Anda tentukan dengan menggunakan async
kata kunci disebut sebagai metode asinkron.
Contoh berikut menunjukkan metode asinkron. Hampir semua yang ada dalam kode akan terlihat akrab untuk Anda.
Anda dapat menemukan contoh Windows Presentation Foundation (WPF) lengkap yang tersedia untuk diunduh dari pemrograman asinkron dengan async dan await dalam C#.
public async Task<int> GetUrlContentLengthAsync()
{
using var client = new HttpClient();
Task<string> getStringTask =
client.GetStringAsync("https://learn.microsoft.com/dotnet");
DoIndependentWork();
string contents = await getStringTask;
return contents.Length;
}
void DoIndependentWork()
{
Console.WriteLine("Working...");
}
Anda dapat mempelajari beberapa praktik dari sampel sebelumnya. Mulailah dengan definisi metode. Ini termasuk pengubah async
. Jenis pengembalian adalah Task<int>
(Lihat bagian "Jenis Pengembalian" untuk opsi lainnya). Nama metode berakhiran Async
. Dalam isi metode , GetStringAsync
mengembalikan Task<string>
. Itu berarti bahwa ketika Anda await
tugas Anda akan mendapatkan string
(contents
). Sebelum menunggu tugas, Anda dapat melakukan pekerjaan yang tidak bergantung pada string
yang berasal dari GetStringAsync
.
Perhatikan dengan seksama operator await
. Ini menangguhkan GetUrlContentLengthAsync
:
-
GetUrlContentLengthAsync
tidak dapat dilanjutkan hinggagetStringTask
selesai. - Sementara itu, kontrol kembali ke pemanggil
GetUrlContentLengthAsync
. - Kontrol dilanjutkan di sini setelah
getStringTask
selesai. - Operator
await
kemudian mengambil hasilstring
darigetStringTask
.
Pernyataan pengembalian menentukan hasil bilangan bulat. Metode apa pun yang sedang menunggu GetUrlContentLengthAsync
akan mengambil nilai panjang.
Jika GetUrlContentLengthAsync
tidak memiliki pekerjaan apa pun yang dapat dilakukan antara memanggil GetStringAsync
dan menunggu penyelesaiannya, Anda dapat menyederhanakan kode Anda dengan memanggil dan menunggu dalam satu pernyataan berikut.
string contents = await client.GetStringAsync("https://learn.microsoft.com/dotnet");
Karakteristik berikut meringkas apa yang membuat contoh sebelumnya sebagai metode asinkron:
Definisi metode mencakup pengubah
async
.Nama metode asinkron, menurut konvensi, diakhiri dengan akhiran "Asinkron".
Jenis pengembalian adalah salah satu jenis berikut:
-
Task<TResult> jika metode Anda memiliki pernyataan pengembalian di mana operand memiliki jenis
TResult
. - Task jika metode Anda tidak memiliki pernyataan pengembalian atau memiliki pernyataan pengembalian tanpa operand.
-
void
jika Anda menulis penanganan aktivitas asinkron. - Jenis lain yang memiliki metode
GetAwaiter
.
Untuk informasi selengkapnya, lihat bagian Tipe pengembalian dan parameter.
-
Task<TResult> jika metode Anda memiliki pernyataan pengembalian di mana operand memiliki jenis
Metode ini biasanya mencakup setidaknya satu
await
ekspresi, yang menandai titik di mana metode tidak dapat dilanjutkan sampai operasi asinkron yang ditunggu selesai. Sementara itu, metode ditangguhkan, dan kontrol kembali ke pemanggil metode. Bagian berikutnya dari topik ini menggambarkan apa yang terjadi pada titik penangguhan.
Dalam metode asinkron, Anda menggunakan kata kunci dan jenis yang disediakan untuk menunjukkan apa yang ingin Anda lakukan, dan pengkompilasi melakukan sisanya, termasuk melacak apa yang harus terjadi ketika kontrol kembali ke titik tunggu dalam metode yang ditangguhkan. Beberapa proses rutin, seperti perulangan dan penanganan pengecualian, bisa sulit ditangani dalam kode asinkron tradisional. Dalam metode asinkron, Anda menulis elemen-elemen ini sebanyak yang Anda lakukan dalam solusi sinkron, dan masalahnya diselesaikan.
Untuk informasi selengkapnya tentang asinkron di versi .NET Framework sebelumnya, lihat TPL dan pemrograman asinkron .NET Framework tradisional.
Apa yang terjadi dalam metode asinkron
Hal terpenting yang perlu dipahami dalam pemrograman asinkron adalah bagaimana alur kontrol berpindah dari metode ke metode. Diagram berikut mengarahkan Anda melalui proses:
Angka dalam diagram sesuai dengan langkah-langkah berikut, dimulai saat metode panggilan memanggil metode asinkron.
Metode pemanggilan memanggil dan menunggu metode
GetUrlContentLengthAsync
asinkron.GetUrlContentLengthAsync
membuat instans HttpClient dan memanggil GetStringAsync metode asinkron untuk mengunduh konten situs web sebagai string.Sesuatu terjadi dalam
GetStringAsync
yang menangguhkan kemajuannya. Mungkin harus menunggu pengunduhan situs web atau aktivitas penghalang lainnya. Untuk menghindari pemblokiran sumber daya,GetStringAsync
menghasilkan kontrol kepada pemanggilnya,GetUrlContentLengthAsync
.GetStringAsync
menghasilkan Task<TResult>, di manaTResult
adalah string, danGetUrlContentLengthAsync
menetapkan tugas ke variabelgetStringTask
. Tugas ini mewakili proses yang sedang berlangsung untuk panggilan keGetStringAsync
, dan memiliki komitmen untuk menghasilkan nilai string aktual ketika pekerjaan telah selesai.Karena
getStringTask
belum ditunggu,GetUrlContentLengthAsync
dapat dilanjutkan dengan pekerjaan lain yang tidak bergantung pada hasil akhir dariGetStringAsync
. Pekerjaan itu diwakili oleh panggilan ke metode sinkronDoIndependentWork
.DoIndependentWork
adalah metode sinkron yang melakukan pekerjaannya dan kembali ke pemanggilnya.GetUrlContentLengthAsync
telah kehabisan pekerjaan yang dapat dilakukannya tanpa hasil darigetStringTask
.GetUrlContentLengthAsync
selanjutnya ingin menghitung dan mengembalikan panjang string yang diunduh, tetapi metode tidak dapat menghitung nilai tersebut sampai metode memiliki string.Oleh karena itu,
GetUrlContentLengthAsync
menggunakan operator tunggu untuk menangguhkan eksekusinya dan mengalihkan kontrol ke metode yang memanggilGetUrlContentLengthAsync
.GetUrlContentLengthAsync
mengembalikanTask<int>
ke pemanggilnya. Tugas ini mewakili janji untuk menghasilkan hasil berupa bilangan bulat yang menunjukkan panjang string yang telah diunduh.Nota
Jika
GetStringAsync
(dan oleh karena itugetStringTask
) selesai sebelumGetUrlContentLengthAsync
menunggunya, kontrol tetap berada diGetUrlContentLengthAsync
. Biaya menangguhkan dan kemudian kembali keGetUrlContentLengthAsync
akan terbuang jika proses asinkron yang disebutgetStringTask
telah selesai danGetUrlContentLengthAsync
tidak perlu menunggu hasil akhir.Dalam metode pemanggilan, pola pemrosesan terus berlanjut. Pemanggil mungkin melakukan pekerjaan lain yang tidak bergantung pada hasil dari
GetUrlContentLengthAsync
sebelum menanti hasil tersebut, atau pemanggil mungkin langsung menanti. Metode panggilan menungguGetUrlContentLengthAsync
, danGetUrlContentLengthAsync
sedang menungguGetStringAsync
.GetStringAsync
menyelesaikan dan menghasilkan hasil string. Hasil string tidak dikembalikan oleh panggilan keGetStringAsync
dengan cara yang mungkin Anda harapkan. (Ingat bahwa metode sudah mengembalikan tugas di langkah 3.) Sebaliknya, hasil string disimpan dalam tugas yang mewakili penyelesaian metode ,getStringTask
. Operator tunggu mengambil hasil darigetStringTask
. Pernyataan penugasan menetapkan hasil yang diambil kecontents
.Ketika
GetUrlContentLengthAsync
memiliki hasil string, metode dapat menghitung panjang string. Kemudian pekerjaanGetUrlContentLengthAsync
juga selesai, dan penanganan aktivitas yang menunggu dapat dilanjutkan. Dalam contoh lengkap di akhir topik, Anda dapat mengonfirmasi bahwa penanganan aktivitas mengambil dan mencetak nilai hasil panjang. Jika Anda baru menggunakan pemrograman asinkron, luangkan waktu satu menit untuk mempertimbangkan perbedaan antara perilaku sinkron dan asinkron. Metode sinkron kembali ketika pekerjaannya selesai (langkah 5), tetapi metode asinkron mengembalikan nilai tugas ketika pekerjaannya ditangguhkan (langkah 3 dan 6). Ketika metode asinkron akhirnya menyelesaikan pekerjaannya, tugas ditandai sebagai selesai dan hasilnya, jika ada, disimpan dalam tugas.
Metode asinkron API
Anda mungkin bertanya-tanya di mana menemukan metode seperti GetStringAsync
yang mendukung pemrograman asinkron. .NET Framework 4.5 atau yang lebih tinggi dan .NET Core berisi banyak anggota yang bekerja dengan async
dan await
. Anda dapat mengenalinya dengan akhiran "Async" yang ditambahkan ke nama anggota, dan jenis pengembaliannya adalah Task atau Task<TResult>. Misalnya, System.IO.Stream
kelas berisi metode seperti CopyToAsync, , ReadAsyncdan WriteAsync bersama metode CopyTosinkron , , Readdan Write.
Windows Runtime juga berisi banyak metode yang dapat Anda gunakan dengan async
dan await
di aplikasi Windows. Untuk informasi selengkapnya, lihat Pemrograman utas dan asinkron untuk pengembangan UWP, dan Pemrograman asinkron (aplikasi Windows Store) dan Mulai Cepat: Memanggil API asinkron di C# atau Visual Basic jika Anda menggunakan versi Windows Runtime yang lebih lama.
Utsan
Metode asinkron dimaksudkan sebagai operasi yang tidak memblokir. Ekspresi await
dalam metode asinkron tidak memblokir utas saat ini saat tugas yang ditunggu sedang berjalan. Sebagai gantinya, ekspresi mendaftarkan sisa metode sebagai kelanjutan dan mengembalikan kontrol ke pemanggil metode asinkron.
async
dan await
tidak menyebabkan utas tambahan dibuat. Metode asinkron tidak memerlukan multithreading karena metode asinkron tidak berjalan pada utasnya sendiri. Metode ini berjalan di konteks sinkronisasi saat ini dan memanfaatkan waktu pada utas hanya ketika metode aktif. Anda dapat menggunakan Task.Run untuk memindahkan pekerjaan yang terikat CPU ke utas latar belakang, tetapi utas latar belakang tidak membantu proses yang hanya menunggu hasil agar tersedia.
Pendekatan berbasis asinkron untuk pemrograman asinkron lebih disukai dibandingkan pendekatan yang ada dalam hampir setiap kasus. Secara khusus, pendekatan ini lebih baik daripada kelas BackgroundWorker untuk operasi yang mengikat I/O karena kodenya lebih sederhana dan Anda tidak perlu khawatir tentang kondisi balapan. Dalam kombinasi dengan metode Task.Run, pemrograman asinkron lebih tepat daripada BackgroundWorker untuk operasi terikat CPU karena pemrograman asinkron memisahkan koordinasi menjalankan kode Anda dari pekerjaan yang dialihkan Task.Run
ke kumpulan utas.
asinkron dan menunggu
Jika Anda menentukan bahwa metode adalah metode asinkron dengan menggunakan pengubah asinkron , Anda mengaktifkan dua kemampuan berikut.
Metode asinkron yang ditandai dapat menggunakan tunggu untuk menunjuk titik penangguhan. Operator
await
memberi tahu pengompilasi bahwa metode asinkron tidak dapat melanjutkan melewati titik itu sampai proses asinkron yang ditunggu selesai. Sementara itu, pengendalian kembali ke pemanggil metode asinkron.Penangguhan sementara metode asinkron pada ekspresi
await
tidak berarti keluar dari metode, dan blok kodefinally
tidak dijalankan.Metode asinkron yang ditandai dapat ditunggu oleh metode yang memanggilnya.
Metode asinkron biasanya berisi satu atau beberapa kemunculan await
operator, tetapi tidak adanya await
ekspresi tidak menyebabkan kesalahan kompilator. Jika metode asinkron tidak menggunakan operator await
untuk menandai titik penangguhan, metode tersebut akan dijalankan seperti metode sinkron, meskipun dengan pengubah async
. Kompilator mengeluarkan peringatan untuk metode tersebut.
async
dan await
adalah kata kunci kontekstual. Untuk informasi dan contoh selengkapnya, lihat topik berikut ini:
- asinkron
- menunggu
Jenis dan parameter pengembalian
Metode asinkron biasanya mengembalikan Task atau Task<TResult>. Di dalam metode async, operator await
diterapkan pada task yang dikembalikan dari pemanggilan metode async lainnya.
Anda menentukan Task<TResult> sebagai jenis pengembalian jika metode berisi return
pernyataan yang menentukan operand jenis TResult
.
Anda menggunakan Task sebagai jenis pengembalian jika metode tidak memiliki pernyataan pengembalian atau memiliki pernyataan pengembalian yang tidak mengembalikan operand.
Anda juga dapat menentukan jenis pengembalian lainnya, asalkan jenis menyertakan metode GetAwaiter
.
ValueTask<TResult> adalah contoh jenis seperti itu. Ini tersedia dalam paket System.Threading.Tasks.Extension NuGet.
Contoh berikut menunjukkan cara Anda mendeklarasikan dan memanggil metode yang mengembalikan Task<TResult> atau Task:
async Task<int> GetTaskOfTResultAsync()
{
int hours = 0;
await Task.Delay(0);
return hours;
}
Task<int> returnedTaskTResult = GetTaskOfTResultAsync();
int intResult = await returnedTaskTResult;
// Single line
// int intResult = await GetTaskOfTResultAsync();
async Task GetTaskAsync()
{
await Task.Delay(0);
// No return statement needed
}
Task returnedTask = GetTaskAsync();
await returnedTask;
// Single line
await GetTaskAsync();
Setiap tugas yang dikembalikan mewakili pekerjaan yang sedang berlangsung. Tugas merangkum informasi tentang status proses asinkron dan, akhirnya, memberikan hasil akhir dari proses atau pengecualian yang terjadi jika proses tidak berhasil.
Metode asinkron juga dapat memiliki void
jenis pengembalian. Jenis pengembalian ini digunakan terutama untuk menentukan penanganan aktivitas, di mana void
jenis pengembalian diperlukan. Penanganan aktivitas asinkron sering berfungsi sebagai titik awal untuk program asinkron.
Metode asinkron yang memiliki jenis pengembalian void
tidak dapat ditunggu, dan pemanggil metode yang mengembalikan void tidak dapat menangkap pengecualian apa pun yang dilemparkan oleh metode tersebut.
Metode asinkron tidak dapat mendeklarasikan parameter masuk, ref , atau keluar , tetapi metode dapat memanggil metode yang memiliki parameter tersebut. Demikian pula, metode asinkron tidak dapat mengembalikan nilai berdasarkan referensi, meskipun dapat memanggil metode dengan nilai pengembalian ref.
Untuk informasi dan contoh selengkapnya, lihat Jenis pengembalian asinkron (C#).
API asinkron dalam pemrograman Windows Runtime memiliki salah satu jenis pengembalian berikut, yang mirip dengan tugas:
- IAsyncOperation<TResult>, yang sesuai dengan Task<TResult>
- IAsyncAction, yang sesuai dengan Task
- IAsyncActionWithProgress<TProgress>
- IAsyncOperationWithProgress<TResult,TProgress>
Konvensi penamaan
Menurut konvensi, metode yang mengembalikan jenis yang biasanya ditunggu (misalnya, Task
, Task<T>
, ValueTask
, ValueTask<T>
) harus memiliki nama yang diakhiri dengan "Async". Metode yang memulai operasi asinkron tetapi tidak mengembalikan jenis yang dapat ditunggu seharusnya tidak memiliki nama yang diakhir dengan "Asinkron", tetapi dapat dimulai dengan "Begin", "Start", atau beberapa kata kerja lainnya untuk menyarankan metode ini tidak mengembalikan atau melempar hasil operasi.
Anda dapat mengabaikan konvensi di mana peristiwa, kelas dasar, atau kontrak antarmuka menyarankan nama yang berbeda. Misalnya, Anda tidak boleh mengganti nama penanganan aktivitas umum, seperti OnButtonClick
.
Artikel terkait (Visual Studio)
Judul | Deskripsi |
---|---|
Cara membuat beberapa permintaan web secara paralel dengan menggunakan asinkron dan menunggu (C#) | Menunjukkan cara memulai beberapa tugas secara bersamaan. |
Jenis pengembalian asinkron (C#) | Mengilustrasikan jenis yang dapat dikembalikan oleh metode asinkron, dan menjelaskan kapan setiap jenis sesuai. |
Batalkan tugas dengan token pembatalan sebagai mekanisme sinyal. | Memperlihatkan cara menambahkan fungsionalitas berikut ke solusi asinkron Anda: - Membatalkan daftar tugas (C#) - Membatalkan tugas setelah jangka waktu tertentu (C#) - Memproses tugas asinkron saat mereka selesai (C#) |
Menggunakan asinkron untuk akses file (C#) | Mencantumkan dan menunjukkan manfaat menggunakan async dan await untuk mengakses file. |
Pola asinkron berbasis tugas (TAP) | Menjelaskan pola asinkron, pola ini didasarkan pada jenis-jenis Task dan Task<TResult>. |
Video Asinkron di Channel 9 | Menyediakan tautan ke berbagai video tentang pemrograman asinkron. |