Search code examples
c#async-awaitcancellationtokensourcecancellation-token

How to cancel await Task that perform multiple task in C#


I have a function at idle time when at certain interval e.g. every 30 seconds, it will perform a polling to hardware for status.

The method name is public static async Task PollCurrentHardwareStatus() which inside this method, it will go through status of every hardwares e.g. I have 4 devices to get connection status (printer module, cash module, coin module, terminal module).

If public touch on main screen, it will divert to next page which I need to cancel the poll status. How to cancel poll status of device in await Task?

I have come through Cancel an Async Task or a List of Tasks (C#) but I seems cannot get the idea where to put the CancellationToken.

My code at 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);
}

Solution

  • I think you can create the CancellationTokenSource from the method which you are calling PollCurrentHardwareStatus(). Please check bellow example:

    Add CancellationTokenSource as a parameter in PollCurrentHardwareStatus method

    public static async Task PollCurrentHardwareStatus(CancellationToken cts)
        {
            // your logic code
            // ...............
        }
    

    Create a CancellationTokenSource and call it on your Page class:

    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();
        }
    }