如何取消等待在C#中执行多个任务的任务

问题描述 投票:0回答:2

我在一定时间间隔的空闲时间有一个功能,例如每隔30秒,它将对硬件执行状态轮询。

方法名称是public static async Task PollCurrentHardwareStatus(),在此方法中,它将通过每个硬件的状态,例如我有4个设备来获得连接状态(打印机模块,现金模块,硬币模块,终端模块)。

如果在主屏幕上公开触摸,它将转移到我需要取消轮询状态的下一页。如何在等待任务中取消设备的轮询状态?

我来自Cancel an Async Task or a List of Tasks (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);
}
c# async-await cancellationtokensource cancellation-token
2个回答
2
投票

我认为您可以从调用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();
    }
}

0
投票

根据MSDN:Cancellation in managed threads

取消是合作的,不会强迫听众。侦听器确定如何优雅地终止以响应取消请求。

你必须创建一个PollCurrentHardwareStatus的重载,它将CancellationToken对象作为输入。该功能应定期检查是否请求取消并正常取消该功能。

这有几个问题:经常是什么?请求取消时该怎么办。

答案符合您的要求。这取决于您应该在50毫秒内取消的中断因素,或取消是否需要一秒钟。例如,如果您的进程在操作员第一次触摸屏幕时被中断,则此操作员可能会在屏幕响应之前等待半秒钟。但是如果每次操作员键入一个字母时你的进程都被中断,那么取消一秒钟可能会很烦人。

因此,您应该多久检查取消的问题取决于使用情况。

async Task PollCurrentHardwareStatus(CancellatinToken token)
{
     token.ThrowIfCancellationRequested();
     DoSomeShortProcessing(); 
     token.ThrowIfCancellationRequested();
     DoSomeOtherProcessing();
     token.ThrowIfcancellationRequested();

等等

如果您调用需要更长时间处理的函数,则会出现问题。最好的办法是将token传递给另一个进程:

LongProcessingFunction(token);

另一个功能应该定期检查令牌。优雅取消取决于此。如果您无法更改其他功能,则无法保证正确快速取消。

async-await对此没有帮助。程序员可以创建等待函数来提供接受CancellationToken的版本。

您会发现所有基本的等待功能(读/写文件,从数据库或互联网获取信息等)都有一个接受CancellationToken的版本。

你可以启动一个线程并在请求取消时终止该线程,但这是相当危险的,因为当线程被杀死时你不知道对象的状态。我不建议这样做。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.