Как отменить ожидание Задача, которая выполняет несколько задач в C # - PullRequest
0 голосов
/ 30 августа 2018

У меня есть функция во время простоя, когда через определенный интервал, например, каждые 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);
}

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Согласно MSDN: Отмена в управляемых потоках

Отмена является кооперативной и не навязывается слушателю. слушатель определяет, как изящно завершить в ответ на запрос на отмену.

Вам нужно будет создать перегрузку PollCurrentHardwareStatus, которая будет принимать объект CancellationToken в качестве входных данных. Функция должна регулярно проверять, запрашивается ли отмена, и корректно отменять функцию.

В этом есть несколько проблем: что это такое? что делать при запросе отмены.

Ответы соответствуют вашим требованиям. Это зависит от последовательности прерываний, которые вы должны были отменить в течение 50 мсек, или от того, может ли отмена потребоваться секунда. Например, если ваш процесс прерывается, когда оператор впервые касается вашего экрана, этот оператор, возможно, пожелает подождать полсекунды, прежде чем экран откликнется. Но если ваш процесс прерывается каждый раз, когда оператор вводит букву, одна секунда для отмены может раздражать.

Так что вопрос о том, как часто вы должны проверять отмену, зависит от использования.

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

и т.д.

Проблема возникает, если вы вызываете функцию, для обработки которой требуется больше времени. Лучше всего было бы передать token другому процессу:

LongProcessingFunction(token);

Другая функция должна регулярно проверять токен. Изящно отмена зависит от этого. Если вы не можете изменить другую функцию, вы не можете гарантировать правильную и быструю отмену.

async-await не поможет вам в этом. Программисты, которые создают ожидаемые функции для предоставления версий, которые принимают CancellationToken, должны решать программисты.

Что вы обнаружите, так это то, что все основные ожидаемые функции (чтение / запись файла, получение информации из базы данных или Интернета и т. Д.) Имеют версию, которая принимает CancellationToken.

Вы можете запустить Поток и убить этот поток при запросе отмены, но это довольно опасно, потому что вы не знаете состояние объекта, когда поток уничтожен. Я бы не советовал.

0 голосов
/ 30 августа 2018

Я думаю, что вы можете создать CancellationTokenSource из метода, который вы вызываете PollCurrentHardwareStatus (). Пожалуйста, проверьте ниже пример:

Добавить 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();
    }
}
...