Saya bermain dengan tugas-tugas Windows 8 WinRT ini, dan saya mencoba untuk membatalkan tugas menggunakan metode di bawah ini, dan itu berfungsi sampai titik tertentu. Metode CancelNotification TIDAK dipanggil, yang membuat Anda berpikir tugas itu dibatalkan, tetapi di latar belakang tugas itu terus berjalan, kemudian setelah selesai, status Tugas selalu selesai dan tidak pernah dibatalkan. Apakah ada cara untuk benar-benar menghentikan tugas saat dibatalkan?
private async void TryTask()
{
CancellationTokenSource source = new CancellationTokenSource();
source.Token.Register(CancelNotification);
source.CancelAfter(TimeSpan.FromSeconds(1));
var task = Task<int>.Factory.StartNew(() => slowFunc(1, 2), source.Token);
await task;
if (task.IsCompleted)
{
MessageDialog md = new MessageDialog(task.Result.ToString());
await md.ShowAsync();
}
else
{
MessageDialog md = new MessageDialog("Uncompleted");
await md.ShowAsync();
}
}
private int slowFunc(int a, int b)
{
string someString = string.Empty;
for (int i = 0; i < 200000; i++)
{
someString += "a";
}
return a + b;
}
private void CancelNotification()
{
}
Jawaban:
Baca di Pembatalan (yang diperkenalkan di NET 4.0 dan sebagian besar tidak berubah sejak saat itu) dan Pola Asynchronous Task-Based , yang menyediakan panduan tentang bagaimana menggunakan
CancellationToken
denganasync
metode.Untuk meringkas, Anda meneruskan
CancellationToken
ke setiap metode yang mendukung pembatalan, dan metode itu harus memeriksanya secara berkala.sumber
CancellationToken
memiliki semua kait yang diperlukan untuk melakukan interop dengan sistem pembatalan kustom, tetapi tidak ada yang dapat membatalkan metode yang tidak dibatalkan.Wait
atauResult
dalamasync
metode; Anda harus selalu menggunakanawait
, yang membuka pengecualian dengan benar.CancellationToken.IsCancellationRequested
dan malah menyarankan untuk melemparkan pengecualian?Atau, untuk menghindari modifikasi
slowFunc
(misalnya Anda tidak memiliki akses ke kode sumber):Anda juga dapat menggunakan metode ekstensi yang bagus dari https://github.com/StephenCleary/AsyncEx dan membuatnya terlihat sesederhana:
sumber
ConfigureAwait
jika tidak Anda bisa terluka di aplikasi UI.using
.Satu kasus yang belum dibahas adalah bagaimana menangani pembatalan di dalam metode async. Ambil contoh kasus sederhana di mana Anda perlu mengunggah beberapa data ke layanan untuk menghitung sesuatu dan kemudian mengembalikan beberapa hasil.
Jika Anda ingin mendukung pembatalan, maka cara termudah adalah dengan memberikan token dan memeriksa apakah telah dibatalkan di antara setiap pemanggilan metode async (atau menggunakan ContinueWith). Jika panggilannya sangat lama, Anda bisa menunggu beberapa saat untuk membatalkan. Saya membuat metode pembantu kecil sebagai gantinya gagal segera setelah dibatalkan.
Jadi untuk menggunakannya, tambahkan saja
.WaitOrCancel(token)
ke panggilan async:Perhatikan bahwa ini tidak akan menghentikan Tugas yang Anda tunggu dan itu akan terus berjalan. Anda harus menggunakan mekanisme yang berbeda untuk menghentikannya, seperti
CancelAsync
panggilan dalam contoh, atau lebih baik lagi lulus dalam yang samaCancellationToken
denganTask
sehingga dapat menangani pembatalan akhirnya. Mencoba untuk membatalkan utas tidak disarankan .sumber
UploadDataAsync
Dapat melanjutkan di latar belakang, tetapi setelah selesai itu tidak akan membuat panggilan keCalculateAsync
karena bagian itu sudah berhenti menunggu). Ini mungkin atau mungkin tidak bermasalah bagi Anda, terutama jika Anda ingin mencoba kembali operasi. MelewatiCancellationToken
semua jalan adalah pilihan yang lebih disukai, bila memungkinkan.Saya hanya ingin menambahkan jawaban yang sudah diterima. Saya terjebak dalam hal ini, tetapi saya mengambil rute yang berbeda dalam menangani acara lengkap. Daripada menjalankan menunggu, saya menambahkan penangan yang selesai untuk tugas.
Di mana event handler terlihat seperti ini
Dengan rute ini, semua penanganan sudah dilakukan untuk Anda, ketika tugas dibatalkan itu hanya memicu pengendali acara dan Anda dapat melihat apakah itu dibatalkan di sana.
sumber