簡體   English   中英

如何取消等待任務在C#中執行多個任務

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM