Лучший подход к таймеру в консольном приложении C # - PullRequest
3 голосов
/ 09 октября 2008

Какой метод таймера лучше всего подходит для консольного пакетного приложения C #, которое должно обрабатываться следующим образом:

  1. Подключение к источникам данных
  2. обработка пакета до истечения времени ожидания или до завершения обработки. «Сделайте что-нибудь с источниками данных»
  3. изящно остановите консольное приложение.

связанный вопрос: Как добавить таймер в консольное приложение C #

Ответы [ 3 ]

4 голосов
/ 28 ноября 2008

Извините за то, что это целое консольное приложение ... но вот полное консольное приложение, которое поможет вам начать работу. Опять же, я извиняюсь за такой большой код, но все остальные, кажется, дают ответ «о, все, что вам нужно сделать, это сделать»:)

using System;
using System.Collections.Generic;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static List<RunningProcess> runningProcesses = new List<RunningProcess>();

        static void Main(string[] args)
        {
            Console.WriteLine("Starting...");

            for (int i = 0; i < 100; i++)
            {
                DoSomethingOrTimeOut(30);
            }

            bool isSomethingRunning = false;

            do
            {
                foreach (RunningProcess proc in runningProcesses)
                {
                    // If this process is running...
                    if (proc.ProcessThread.ThreadState == ThreadState.Running)
                    {
                        isSomethingRunning = true;

                        // see if it needs to timeout...
                        if (DateTime.Now.Subtract(proc.StartTime).TotalSeconds > proc.TimeOutInSeconds)
                        {
                            proc.ProcessThread.Abort();
                        }
                    }
                }
            }
            while (isSomethingRunning);

            Console.WriteLine("Done!");    

            Console.ReadLine();
        }

        static void DoSomethingOrTimeOut(int timeout)
        {
            runningProcesses.Add(new RunningProcess
            {
                StartTime = DateTime.Now,
                TimeOutInSeconds = timeout,
                ProcessThread = new Thread(new ThreadStart(delegate
                  {
                      // do task here...
                  })),
            });

            runningProcesses[runningProcesses.Count - 1].ProcessThread.Start();
        }
    }

    class RunningProcess
    {
        public int TimeOutInSeconds { get; set; }

        public DateTime StartTime { get; set; }

        public Thread ProcessThread { get; set; }
    }
}
3 голосов
/ 09 октября 2008

Это зависит от того, насколько точно вы хотите, чтобы ваше время остановки было. Если ваши задачи в пакете достаточно быстрые, и вам не нужно быть очень точным, я бы постарался сделать его однопоточным:

DateTime runUntil = DataTime.Now.Add(timeout);
forech(Task task in tasks)
{
   if(DateTime.Now >= runUntil)
   {
        throw new MyException("Timeout");
   }
   Process(task);
}

В противном случае вам нужно перейти на многопоточность, что всегда сложнее, потому что вам нужно выяснить, как завершить задачу посередине, не вызывая побочных эффектов. Вы можете использовать таймер из System.Timers: http://msdn.microsoft.com/en-us/library/system.timers.timer(VS.71).aspx или Thread.Sleep. Когда происходит событие тайм-аута, вы можете завершить поток, который выполняет фактическую обработку, очистить и завершить процесс.

2 голосов
/ 09 октября 2008

Когда вы говорите «до истечения времени ожидания», вы имеете в виду «продолжать обработку в течение часа, а затем остановить»? Если это так, я, вероятно, просто сделаю это очень явно: сначала отработайте, когда вы хотите закончить, затем в цикле обработки проверьте, достиг ли вы того времени или нет. Это невероятно просто, легко тестировать и т. Д. С точки зрения тестируемости вам могут понадобиться фальшивые часы, которые позволят вам программно установить время.

РЕДАКТИРОВАТЬ: Вот некоторые псевдокод, чтобы попытаться уточнить:

List<DataSource> dataSources = ConnectToDataSources();
TimeSpan timeout = GetTimeoutFromConfiguration(); // Or have it passed in!
DateTime endTime = DateTime.UtcNow + timeout;

bool finished = false;
while (DateTime.UtcNow < endTime && !finished)
{
    // This method should do a small amount of work and then return
    // whether or not it's finished everything
    finished = ProcessDataSources(dataSources);
}

// Done - return up the stack and the console app will close.

Это просто использование встроенных часов, а не интерфейса часов, который можно смоделировать и т. Д. - но это, вероятно, делает общее подходящее проще для понимания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...