我在一定时间间隔的空闲时间有一个功能,例如每隔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);
}
我认为您可以从调用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: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的版本。
你可以启动一个线程并在请求取消时终止该线程,但这是相当危险的,因为当线程被杀死时你不知道对象的状态。我不建议这样做。