Отмена токена из бесконечной параллели. От l oop до события - PullRequest
1 голос
/ 12 февраля 2020

Я написал некоторый код, где я использую Parallel.Foreach, чтобы несколько элементов работали параллельно с бесконечным l oop, т.е. работали нормально после каждых 60 сек c.

Но здесь мое сообщение может быть измененным пользователем в любое время, и мне нужно повторно обработать новое сообщение. Для этого мне нужно отменить бесконечный Parallel.Foreach l oop для повторной обработки обновленного сообщения.

, когда я пытаюсь повторно обработать основной метод, он работает нормально для нового сообщения, но работает дважды, потому что предыдущие запланированные задания не отменяются. Я предполагаю, что мне нужно отменить процесс из Parrallel.Foreach l oop и перезапустить снова для обновления сообщения с новым расписанием.

Так что любой может помочь мне отменить задачу в очереди, которая уже запланирована на следующую 60 секунд.

static void Main(string[] args)
    {
        List<RealTimeMessage> messages = GetRealTimeMessage();
        Parallel.ForEach(messages, (message) =>
        {
            processMessage(message);
        });

        Console.ReadLine();
    }

private static async void processMessage(RealTimeMessage message)
{
    try
    {
        while (true)
        {
            await Task.Delay(TimeSpan.FromSeconds(60));
            await Task.Run(() => ProceesRequest(message));
        }
    }
    catch (Exception)
    {
        Console.WriteLine("Critical error");
    }
}

private static List<RealTimeMessage> GetRealTimeMessage()
{
    List<RealTimeMessage> realTimeMessages = new List<RealTimeMessage>();
    realTimeMessages.Add(new RealTimeMessage { MessageText = "Message 4", IntervalTime = "1", MessageType = "AIDX", TimeOfDay = "" });
    realTimeMessages.Add(new RealTimeMessage { MessageText = "Message 5", IntervalTime = "2", MessageType = "AMSX", TimeOfDay = "" });

    return realTimeMessages;
}
private static void ProceesRequest(RealTimeMessage message)
{
 // do domething
}

1 Ответ

1 голос
/ 12 февраля 2020
  1. Это неправильное использование Parallel.ForEach, используйте Task.WhenAll вместо
  2. Не запускайте Task в ProcessMessage (это может быть преднамеренным, однако это выглядит как ошибка).
  3. Используйте CancellationToken до Отмена a Задание
  4. Не используйте async void, если это не для события
  5. Используйте стандартный регистр для имен методов
  6. Не используйте while(true) Используйте while (!token.IsCancellationRequested)

Когда все вещи рассмотрены, это будет выглядеть примерно так

static async Task Main(string[] args)
{
   var ts = new CancellationTokenSource();

   var messages = GetRealTimeMessage();
   var tasks = messages.Select(x => ProcessMessage(x, ts.Token));

   Console.WriteLine("Press any key to cancel tasks")
   Console.ReadKey();

   ts.Cancel();
   await Task.WhenAll(tasks);

   Console.WriteLine("All finished");
   Console.ReadKey(); 
}

private static async Task ProcessMessage( RealTimeMessage message, CancellationToken token )
{
   try
   {
      while (!token.IsCancellationRequested)
      {
         await Task.Delay(TimeSpan.FromSeconds(60), token);
         ProcessRequest(message);
      }
   }
   catch (OperationCanceledException)
   {
      Console.WriteLine("Operation Cancelled");
   }
   catch (Exception ex)
   {
      Console.WriteLine("Critical error: " +  ex.Message);
   }
}

Чтобы отменить ваши задачи , просто позвоните ts.Cancel().

...