Ini bukan duplikat dari "Cara memanggil metode async dengan aman di C # tanpa menunggu" .
Bagaimana cara saya dengan baik menekan peringatan berikut?
peringatan CS4014: Karena panggilan ini tidak ditunggu, pelaksanaan metode saat ini berlanjut sebelum panggilan selesai. Pertimbangkan untuk menerapkan operator 'menunggu' ke hasil panggilan.
Contoh sederhana:
static async Task WorkAsync()
{
await Task.Delay(1000);
Console.WriteLine("Done!");
}
static async Task StartWorkAsync()
{
WorkAsync(); // I want fire-and-forget
// more unrelated async/await stuff here, e.g.:
// ...
await Task.Delay(2000);
}
Apa yang saya coba dan tidak suka:
static async Task StartWorkAsync()
{
#pragma warning disable 4014
WorkAsync(); // I want fire-and-forget here
#pragma warning restore 4014
// ...
}
static async Task StartWorkAsync()
{
var ignoreMe = WorkAsync(); // I want fire-and-forget here
// ...
}
Diperbarui , karena jawaban yang diterima asli telah diedit, saya telah mengubah jawaban yang diterima menjadi yang menggunakan C # 7.0 discards , karena menurut saya tidak ContinueWith
sesuai di sini. Kapan pun saya perlu mencatat pengecualian untuk operasi kebakaran dan lupakan, saya menggunakan pendekatan yang lebih rumit yang diusulkan oleh Stephen Cleary di sini .
sumber
#pragma
tidak baik?async void
metode pembantu.Jawaban:
Dengan C # 7 sekarang Anda dapat menggunakan discards :
sumber
_ = ...
di otakku.#pragma warning disable CSxxxx
terlihat lebih jelek daripada yang dibuang;)Anda dapat membuat metode ekstensi yang akan mencegah peringatan. Metode ekstensi bisa kosong atau Anda bisa menambahkan penanganan pengecualian di
.ContinueWith()
sana.Namun ASP.NET menghitung jumlah tugas yang sedang berjalan, sehingga tidak akan bekerja dengan
Forget()
ekstensi sederhana seperti yang tercantum di atas dan malah gagal dengan pengecualian:Dengan .NET 4.5.2 dapat diselesaikan dengan menggunakan
HostingEnvironment.QueueBackgroundWorkItem
:sumber
TplExtensions.Forget
. Ada banyak kebaikan di bawahMicrosoft.VisualStudio.Threading
. Saya berharap ini tersedia untuk digunakan di luar Visual Studio SDK.Anda dapat menghias metode ini dengan atribut berikut:
Pada dasarnya Anda memberi tahu kompiler bahwa Anda tahu apa yang Anda lakukan dan tidak perlu khawatir tentang kemungkinan kesalahan.
Bagian penting dari kode ini adalah parameter kedua. Bagian "CS4014:" adalah yang menekan peringatan. Anda dapat menulis apa pun yang Anda inginkan di sisanya.
sumber
[SuppressMessage("Compiler", "CS4014")]
menekan pesan di jendela Daftar Kesalahan, tetapi jendela Output masih menampilkan garis peringatanDua cara saya berurusan dengan ini.
Simpan ke variabel buang (C # 7)
Contoh
_ = Task.Run(() => DoMyStuff()).ConfigureAwait(false);
Sejak diperkenalkannya discards di C # 7, saya sekarang menganggap ini lebih baik daripada menekan peringatan. Karena itu tidak hanya menekan peringatan, tetapi juga membuat niat api-dan-lupa menjadi jelas.
Selain itu, kompiler akan dapat mengoptimalkannya dalam mode rilis.
Tekan saja
adalah solusi yang cukup bagus untuk "memecat dan melupakan".
Alasan mengapa peringatan ini ada adalah karena dalam banyak kasus itu bukan niat Anda untuk menggunakan metode yang mengembalikan tugas tanpa menunggu itu. Menekan peringatan ketika Anda berniat untuk menembak dan melupakan itu masuk akal.
Jika Anda kesulitan mengingat cara mengeja
#pragma warning disable 4014
, cukup biarkan Visual Studio menambahkannya untuk Anda. Tekan Ctrl +. untuk membuka "Tindakan Cepat" dan kemudian "Menekan CS2014"Semua seutuhnya
Adalah bodoh untuk membuat metode yang membutuhkan beberapa kutu untuk dieksekusi, hanya untuk tujuan menekan peringatan.
sumber
[MethodImpl(MethodImplOptions.AggressiveInlining)] void Forget(this Task @this) { } /* ... */ obj.WorkAsync().Forget();
AggressiveInlining
kompiler hanya mengabaikannya untuk alasan apa pun#pragma warning disable 4014
dan kemudian mengembalikan peringatan setelahnya dengan#pragma warning restore 4014
. Masih berfungsi tanpa kode kesalahan, tetapi jika Anda tidak menambahkan nomor kesalahan itu akan menekan semua pesan.Cara mudah untuk menghentikan peringatan adalah dengan hanya menetapkan Tugas saat memanggilnya:
Maka dalam posting asli Anda, Anda akan melakukan:
sumber
task
terlihat seperti variabel lokal yang terlupakan. Hampir seperti kompiler harus memberi saya peringatan lain, sesuatu seperti "task
ditugaskan tetapi nilainya tidak pernah digunakan", selain itu tidak. Juga, itu membuat kode lebih mudah dibaca. Saya sendiri menggunakan pendekatan ini .fireAndForget
... jadi saya berharap untuk selanjutnya tidak direferensikan.Alasan untuk peringatan itu adalah WorkAsync mengembalikan
Task
yang tidak pernah dibaca atau ditunggu. Anda dapat mengatur kembali tipe WorkAsyncvoid
dan peringatan akan hilang.Biasanya metode mengembalikan a
Task
ketika penelepon perlu mengetahui status pekerja. Dalam kasus api-dan-lupa, kekosongan harus dikembalikan agar menyerupai bahwa penelepon independen dari metode yang disebut.sumber
Mengapa tidak membungkusnya di dalam metode async yang mengembalikan batal? Agak panjang tapi semua variabel digunakan.
sumber
Saya menemukan pendekatan ini secara tidak sengaja hari ini. Anda dapat menentukan delegasi dan menetapkan metode async ke delegasi terlebih dahulu.
dan menyebutnya seperti itu
...
Saya pikir itu menarik bahwa kompiler tidak akan memberikan peringatan yang sama persis ketika menggunakan delegasi.
sumber
(new Func<Task>(AsyncOperation))()
meskipun IMO itu masih agak terlalu bertele-tele.