[英]How to cancel an asynchronous Task?
我有一個加載數據的方法,例如:
public async GetCustomers()
{
await Task.Run(() => {
for (int i = 0; i < 99; i++)
customers = customerRequest.GetCustomers();
});
}
customerRequest
是一個使用HttpClient
連接到WebApi服務器的簡單類。 調用堆棧如下:
method-> request-> controller action-> server layer-> repository-> db
目前,控制器操作返回IHttpActionResult
,而服務和存儲庫層返回IEnumerable<Customer>
。 所有方法都是同步調用的。
出於測試目的,我添加了for
循環以增加任務的延遲並查看正在執行的SQL語句。
如果用戶決定關閉表單,則任務仍在后台執行,SQL語句仍會發送到數據庫。
取消此類任務的正確方法是什么?
您想要使用CancellationTokenSource
,並將其CancellationToken
傳遞給您的方法。 表單關閉時,調用CancellationTokenSource.Cancel
。
但請注意,您希望將CancellationToken
傳遞給實際使用它的方法。 正如我在博客中描述的那樣, Task.Run
不是其中之一 。
你真正想要做的是從最低級別(在客戶端)開始,並將CancellationToken
傳遞給你正在使用的任何HttpClient
方法(即, 像這樣 )。
然后繼續努力。 我還建議讓你的代碼異步。 當你完成后,你應該得到一個如下所示的GetCustomers
:
public async Task GetCustomersAsync(CancellationToken token)
{
for (int i = 0; i < 99; i++)
customers = await customerRequest.GetCustomersAsync(token);
}
如果你真的想確定(tm)沒有虛假請求,你也可以在做請求之前明確檢查令牌:
public async Task GetCustomersAsync(CancellationToken token)
{
for (int i = 0; i < 99; i++)
{
token.ThrowIfCancellationRequested();
customers = await customerRequest.GetCustomersAsync(token);
}
}
如果這對您很重要,您還可以在服務器端處理取消 。
Checkout CancellationTokenSource。 您可以保留其中一個長壽命按鈕或關閉事件調用取消()。 如果您希望取消所有任務,只需將其傳遞給您的所有任務。 該任務將拋出異常,因此請確保包裝try catch。 您還可以檢查您的任務中是否已取消取消請求以嘗試以優雅的方式突破。
var cts = new CancellationTokenSource();
await Task.Run(() =>
{
//do work, will throw if cts.Cancel() is called
}, cts.Token);
//wait 2 seconds then cancel
await Task.Delay(2000);
cts.Cancel();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.