[英]How to cancel await Task that perform multiple task in C#
我有一個空閑時間的功能,該功能每隔一定的時間間隔(例如每30秒)就會對硬件進行一次輪詢以獲取狀態。
該方法的名稱是public static async Task PollCurrentHardwareStatus()
,該方法內部將遍歷每個硬件的狀態,例如,我有4個設備來獲取連接狀態(打印機模塊,現金模塊,硬幣模塊,終端模塊)。
如果在主屏幕上公開觸摸,它將轉到下一個頁面,我需要取消投票狀態。 如何在等待任務中取消設備的輪詢狀態?
我遇到了取消異步任務或任務列表(C#)的問題,但是我似乎不知道將CancellationToken放在哪里。
我在PollCurrentHardwareStatus
代碼:-
public static async Task PollCurrentHardwareStatus()
{
try
{
//POLLING CARD READER
if (GlobVars.HwIDTech.Enabled)
{
if (IDTechDevice.PingForReply())
{
LogEvents($"[App] Terminal OK.", EventLogEntryType.Information);
AppDeviceStatus.strIDTechStatus = StatusMessageIDTech.strSuccessID;
}
else
{
LogEvents($"[App] IDTechDevice: Not found/Disconnected", EventLogEntryType.Information);
AppDeviceStatus.strIDTechStatus = StatusMessageIDTech.strErrorID;
}
}
//POLLING PRINTER
if (GlobVars.HwCustom.Enabled)
{
string description = string.Empty;
int status = 0;
PrintMain.PrinterGetStatus(ref description, ref status);
if (status == 0)
{
AppDeviceStatus.strPrinterStatus = StatusMessagePrinter.strSuccessID;
}
else
{
LogEvents($"[App] Printer error: {description}", EventLogEntryType.Information);
AppDeviceStatus.strPrinterStatus = StatusMessagePrinter.strErrorID;
}
}
//POLLING CASH COIN MODULE
if (GlobVars.HwB2B.Enabled && GlobVars.HwBCR.Enabled)
{
string B2BStatus = await CCMain.GetCurrentDeviceStatus();
if (B2BStatus == "DISABLED")
{
AppDeviceStatus.strB2BStatus = StatusMessageB2B.strSuccessID;
LogEvents($"[App] Poll B2B device: Status - OK.", EventLogEntryType.Information);
}
else
{
LogEvents($"[App] Poll B2B device: Status - {B2BStatus}.", EventLogEntryType.Information);
AppDeviceStatus.strB2BStatus = StatusMessageB2B.strErrorID;
}
if (ModuleCoins.OpenConnection())
{
await ModuleCoins.PerformSelfTest();
AppDeviceStatus.strBCRStatus = StatusMessageBCR.strSuccessID;
}
else
{
AppDeviceStatus.strBCRStatus = StatusMessageBCR.strErrorID;
}
}
UpdateErrorStatus();
}
catch (Exception ex)
{
LogEvents($"[App] Poll hardware status : Ex-{ex.Message}. Stack Trace-{ex.StackTrace}", EventLogEntryType.Error);
}
await Task.Delay(100);
}
我認為您可以從調用PollCurrentHardwareStatus()的方法中創建CancellationTokenSource。 請檢查以下示例:
將CancellationTokenSource添加為PollCurrentHardwareStatus方法中的參數
public static async Task PollCurrentHardwareStatus(CancellationToken cts)
{
// your logic code
// ...............
}
創建一個CancellationTokenSource並在您的Page類上調用它:
public class Page
{
private CancellationTokenSource cancellationTokenSource;
public Page()
{
cancellationTokenSource = new CancellationTokenSource();
}
public async void CallPoll()
{
await PollCurrentHardwareStatus(cancellationTokenSource.Token);
}
public void OnCancelPoll(object sender, EventArgs e)
{
cancellationTokenSource.Cancel();
}
}
根據MSDN: 托管線程中的取消
取消是協作的,不會強制偵聽器。 偵聽器確定如何優雅地終止以響應取消請求。
您必須創建PollCurrentHardwareStatus
的重載,該重載將CancellationToken對象作為輸入。 該功能應定期檢查是否請求取消並優雅地取消該功能。
這有幾個問題:什么是規則? 請求取消時該怎么辦。
答案取決於您的要求。 這取決於您是否應該在50毫秒內取消中斷,還是取消可能需要一秒鍾。 例如,如果當操作員第一次觸摸您的屏幕時您的過程被中斷,則該操作員可能希望等待半秒鍾才能響應屏幕。 但是,如果操作員每次輸入字母都會中斷您的過程,那么取消一秒鍾可能會很煩人。
因此,您應該多久檢查一次取消的問題取決於用法。
async Task PollCurrentHardwareStatus(CancellatinToken token)
{
token.ThrowIfCancellationRequested();
DoSomeShortProcessing();
token.ThrowIfCancellationRequested();
DoSomeOtherProcessing();
token.ThrowIfcancellationRequested();
等等
如果您調用需要較長時間處理的函數,則會出現問題。 最好的辦法是將token
傳遞給其他進程:
LongProcessingFunction(token);
其他功能應定期檢查令牌。 優雅地取消取決於此。 如果您不能更改其他功能,則不能保證正確,快速地取消。
async-await對此沒有幫助。 由創建等待函數的程序員來提供接受CancellationToken的版本。
您會發現,所有基本的等待功能(讀/寫文件,從數據庫或互聯網獲取信息等)都具有接受CancellationToken的版本。
您可以啟動一個線程並在請求取消時終止該線程,但這是相當危險的,因為在終止線程時您不知道對象的狀態。 我不建議這樣做。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.