3

对于必须按以下方式处理的 C# 控制台批处理应用程序,这是最好的计时器方法:

  1. 连接到数据源
  2. 处理批处理,直到发生超时或处理完成。“用数据源做点什么”
  3. 优雅地停止控制台应用程序。

相关问题:如何将计时器添加到 C# 控制台应用程序

4

3 回答 3

5

抱歉,这是一个完整的控制台应用程序……但这是一个完整的控制台应用程序,可以帮助您入门。再一次,我为这么多代码道歉,但其他人似乎都在给出“哦,你所要做的就是去做”的答案:)

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; }
    }
}
于 2008-11-28T11:47:41.733 回答
3

这取决于您希望停止时间有多准确。如果您在批处理中的任务相当快并且您不需要非常准确,那么我会尝试使其成为单线程:

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。当超时事件发生时,您可以终止执行实际处理的线程,清理并结束进程。

于 2008-10-09T08:55:06.683 回答
2

当您说“直到发生超时”时,您的意思是“继续处理一个小时然后停止”吗?如果是这样,我可能会说得非常明确——在你想完成的时候开始工作,然后在你的处理循环中,检查你是否已经到了那个时间。它非常简单,易于测试等。就可测试性而言,您可能需要一个假时钟,它可以让您以编程方式设置时间。

编辑:这里有一些伪代码试图澄清:

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.

那只是使用内置时钟而不是可以模拟的时钟接口等 - 但它可能使一般适当的更容易理解。

于 2008-10-09T08:43:45.507 回答