C# 如何正确地每分钟执行一次线程?

C# 如何正确地每分钟执行一次线程?,c#,multithreading,system.timers.timer,C#,Multithreading,System.timers.timer,这个问题分为两部分。 我有一个控制台应用程序,它从多个服务器获取信息,并将这些信息保存到数据库中。为了使它能够同时执行,我使用了线程。我正试图每分钟都自动执行 搜索stackoverflow时,我发现这可以工作: var timer = new System.Threading.Timer((e) => { var models = ServerHandler.GetServerModels(); foreach (v

这个问题分为两部分。 我有一个控制台应用程序,它从多个服务器获取信息,并将这些信息保存到数据库中。为了使它能够同时执行,我使用了线程。我正试图每分钟都自动执行

搜索stackoverflow时,我发现这可以工作:

   var timer = new System.Threading.Timer((e) =>
        {
            var models = ServerHandler.GetServerModels();

            foreach (var m in models)
            {
                ServerHandler.MakeThreads(m);
            }

            Console.WriteLine("Running...");
            Console.WriteLine("Press 'X' to exit or close the window, i : " + i);

            i++;


        }, null, 0, TimeSpan.FromMinutes(1).Seconds);
然而,这并不像预期的那样工作,它只执行一次。例如,如果我更改为:

TimeSpan.FromMinutes(0.5).Seconds
或:

然后它就起作用了。 我做错了什么

问题的第二部分:

当这真的像我上面展示的那样起作用时,会发生一些其他的事情。 进程连续运行,在474个线程之后崩溃,并表示系统内存不足

我尝试使用线程睡眠,但当我这样做,它停止执行后,它已经运行了一次

如果有帮助的话,包括:

public static void MakeThreads(ServerModel model)
{
    Thread thread = new Thread(() => SaveServerInfo(model));
    thread.Start();
    //Thread.Sleep(1);
    //thread.Join();

}

如何使其工作?

在您的第一个问题中,使用.Seconds将只返回秒值,但您将分钟值定义为.5,因此秒始终为零

如果要返回秒数,需要使用TotalSeconds

TimeSpan.FromMinutes(0.5).TotalSeconds
在您使用的时间跨度中,您应该定义毫秒。因此,您将获得大量线程,因为它每30毫秒运行一次,而不是每30000毫秒运行一次

所以使用

TimeSpan.FromMinutes(0.5).TotalMilliseconds
或者我总是觉得更容易

(int)(1000 * 60 * 0.5)  // Then you just replace the 0.5 with the number of seconds. 

在第一个问题中,使用.Seconds将只返回秒值,但您将分钟值定义为.5,因此秒始终为零

如果要返回秒数,需要使用TotalSeconds

TimeSpan.FromMinutes(0.5).TotalSeconds
在您使用的时间跨度中,您应该定义毫秒。因此,您将获得大量线程,因为它每30毫秒运行一次,而不是每30000毫秒运行一次

所以使用

TimeSpan.FromMinutes(0.5).TotalMilliseconds
或者我总是觉得更容易

(int)(1000 * 60 * 0.5)  // Then you just replace the 0.5 with the number of seconds. 

基本上,计时器完全按照它应该做的做:每0.5秒运行一次代码。:)在你的情况下,这是个问题

(请检查语法错误等,我在记事本上写的)

长期解决方案

您的问题似乎是无法控制线程。下面是我如何解决它的:(这个长的解决方案或多或少说明了它是如何工作的)

while(true)
{    
//我们想在0.5秒内再次运行它。
DateTime start=DateTime.UtcNow.AddSeconds(0.5);
线程[]线程=新线程[models.Count];
对于(int i=0;i SaveServerInfo((ServerModel)a));
线程[i]。开始(模型[i]);
}

对于(inti=0;i基本上计时器完全执行它应该执行的操作:每0.5秒运行一次代码。:)在您的情况下,这是一个问题

(请检查语法错误等,我在记事本上写的)

长期解决方案

您的问题似乎是无法控制线程。下面是我如何解决它的:(这个长的解决方案或多或少说明了它是如何工作的)

while(true)
{    
//我们想在0.5秒内再次运行它。
DateTime start=DateTime.UtcNow.AddSeconds(0.5);
线程[]线程=新线程[models.Count];
对于(int i=0;i SaveServerInfo((ServerModel)a));
线程[i]。开始(模型[i]);
}


对于(int i=0;i'TimeSpan.FromMinutes(1).Seconds'返回0。您想要的'TimeSpan.FromMinutes(1).TotalSeconds'返回60。我会使用
TimeSpan
重载。那么
TimeSpan.FromSeconds(60).Seconds
?!'TimeSpan.FromMinutes(1).Seconds'返回0。您想要的'TimeSpan.FromMinutes(1)呢.TotalSeconds'返回60。我会使用
TimeSpan
重载。那么
TimeSpan.FromSeconds(60)呢.Seconds
?!尝试过了,它每秒钟运行一次,直到我有475个线程,然后崩溃,所以执行时间比间隔长。这是一个性能问题。你应该尝试其他方法…@Ra3IDeN看到我更新的答案的第二部分。好的,我想这就是我正在寻找的。尽管我希望得到一个s暗示澄清。我复制了你答案的第二部分,并计算出每30秒执行一次。我已经让应用程序运行了3分钟,但它只执行了一次。我的代码当前:(int)TimeSpan.frommins(1000*60*0.5).TotalSeconds)@CathalMF老实说,我不知道为什么在
Timer
类已经接受
TimeSpan
的情况下,还要费心将
TimeSpan
转换成整数。如果你只是按原样使用它,就不会有混乱。试过了,它每秒钟运行一次,直到我有475个线程,然后崩溃,所以执行时间比间隔长。这是一个性能问题。你应该试试别的…@Ra3IDeN看到我更新的答案的第二部分了。好吧,我想这就是我想要的。尽管我希望能简单地澄清一下。我复制了你答案的第二部分,并计算出每30秒执行一次。我已经让应用程序运行了3分钟,它只执行了一次。我的代码当前:(int)TimeSpan.frommins(1000*60*0.5).TotalSeconds)@CathalMF老实说,我不知道为什么你还要费心将
TimeSpan
转换成整数,而
Timer
类已经接受
TimeSpan
。如果您只是按原样使用它,就不会有任何可能的混淆。这不起作用。第一个soloution在我没有在调试器中运行时就给了我一个索引超出范围异常。第二个解决方案只运行了一次线程,然后就停止了。@Ra3IDeN在第一个示例中,我确实忘记了线程的开始;现在已经修好了。第二个解决方案按原样工作。如果您得到一个索引超出范围的异常,那么您正在更改线程中的集合——这在任何情况下都是不允许的,您正在创建一个竞争条件!至于你声称它不起作用,我刚刚创建了一个最小的测试用例,它工作得很好;欢迎光临