我在空闲时间有一定的功能,例如在一定的时间间隔每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);
}
答案 0 :(得分: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();
}
}
答案 1 :(得分: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的版本。
您可以启动一个线程并在请求取消时杀死该线程,但这非常危险,因为在杀死该线程时您不知道对象的状态。我不建议这样做。