C# .NET调度多个操作:单计时器与单计时器操作

C# .NET调度多个操作:单计时器与单计时器操作,c#,.net,multithreading,timer,scheduled-tasks,C#,.net,Multithreading,Timer,Scheduled Tasks,我正在.NET中开发一个Windows服务应用程序,它执行许多功能(它是一个WCF服务主机),其中一个目标是运行计划任务 我选择为每个操作创建一个System.Threading.Timer,将dueTime设置为下一次执行,并且没有避免重入的周期。 每次操作结束时,它都会更改dueTime以匹配下一次计划执行 大多数操作计划每分钟运行一次,但不是全部一起运行,而是彼此延迟几秒钟 现在,在添加了一些操作(大约30次)之后,计时器似乎开始不准确,操作延迟了几秒钟,甚至几分钟 我直接在计时器的回调方

我正在.NET中开发一个Windows服务应用程序,它执行许多功能(它是一个WCF服务主机),其中一个目标是运行计划任务

我选择为每个操作创建一个System.Threading.Timer,将dueTime设置为下一次执行,并且没有避免重入的周期。
每次操作结束时,它都会更改dueTime以匹配下一次计划执行

大多数操作计划每分钟运行一次,但不是全部一起运行,而是彼此延迟几秒钟

现在,在添加了一些操作(大约30次)之后,计时器似乎开始不准确,操作延迟了几秒钟,甚至几分钟

我直接在计时器的回调方法中运行操作逻辑,因此运行的线程应该与计时器相同

我是否应该创建一个任务来运行该操作,而不是在回调方法中运行它以提高准确性

或者我应该使用一个固定时间(1秒)的计时器来检查哪些操作需要启动?
我不喜欢最后一个选项,因为它将更难处理可重入性。

在线程池线程上激发,因此您可能会发现,当您添加大量计时器时,您正在耗尽线程池

您可以更改线程池的大小,或者确保计时器少于线程池的大小

从回调中启动任务可能不会有什么帮助,因为您将要争夺来自同一线程池的线程。除非您使用。

在线程池中激发线程,否则您可能会发现,当您添加大量计时器时,您正在耗尽线程池

您可以更改线程池的大小,或者确保计时器少于线程池的大小


从回调中启动任务可能不会有什么帮助,因为您将要争夺来自同一线程池的线程。除非您使用。

我们通常设置多个计时器来处理单个服务中的不同操作。我们在服务启动/停止/关闭事件上设置间隔和启动、停止计时器(并且有一个变量指示每个事件的状态,即bool Stopped) 当计时器计时结束时,我们停止计时器,运行处理(这可能需要一段时间,具体取决于进程,也就是说,如果间隔较短,则可能需要更长的时间。)(此代码需要处于try--catch状态,以便继续出错) 代码处理后,我们检查停止的变量,如果它没有停止,我们再次启动计时器(这将处理您提到的重新进入,并允许代码尽可能地保持间隔) 据我所知,计时器通常在大约100毫秒后更精确,但应该足够接近您想要做的事情

我们已经运行这个概念多年了,它并没有让我们失望

如果您将这些任务作为ASP.NET应用程序的子系统运行,那么还应该看看HangFire,它可以处理后台处理,从而消除对windows服务的需求


计时器需要有多精确?您可以始终使用单个计时器并同时运行多个处理线程?或者,如果不太重要,则将对某些操作的调用排队。

我们通常设置多个计时器以处理单个服务中的不同操作。我们设置时间间隔并在服务启动时启动、停止计时器top/Shutdown事件(并且有一个变量指示每个事件的状态,即bool Stopped) 当计时器计时结束时,我们停止计时器,运行处理(这可能需要一段时间,具体取决于进程,也就是说,如果间隔较短,则可能需要更长的时间。)(此代码需要处于try--catch状态,以便继续出错) 代码处理后,我们检查停止的变量,如果它没有停止,我们再次启动计时器(这将处理您提到的重新进入,并允许代码尽可能地保持间隔) 据我所知,计时器通常在大约100毫秒后更精确,但应该足够接近您想要做的事情

我们已经运行这个概念多年了,它并没有让我们失望

如果您将这些任务作为ASP.NET应用程序的子系统运行,那么还应该看看HangFire,它可以处理后台处理,从而消除对windows服务的需求


计时器需要精确到什么程度?您可以始终使用单个计时器并同时运行多个处理线程?或者在不太关键的情况下将调用排入某些操作的队列。

好的,我做出了一个决定:由于我无法轻松重现行为,我选择解决根本问题,并使用服务进程仅用于:

  • 为客户端完成的WCF请求提供服务
  • 计划操作(这是有问题的)
  • 每个可能占用CPU的操作都由另一个进程执行,该进程直接由主进程(带有System.Diagnostics.process及其事件)控制,并通过WCF与其通信

    当我启动辅助进程时,我通过命令行将主进程的PID传递给它。如果后者被终止,则会触发process.Exited事件,我也可以关闭子进程

    这样,主服务通常不会占用太多CPU时间,并且可以自由地愉快地进行调度,而不会出现延迟


    多亏了所有给我提建议的人!

    好的,我做出了一个决定:因为我无法轻松复制行为,所以我选择解决根本问题,并使用服务流程仅:

  • 为客户端完成的WCF请求提供服务
  • 计划操作(这是有问题的)
  • 每个可能占用CPU的操作都由另一个进程执行,该进程直接由主进程(带有System.Diagnostics.process及其事件)控制,并通过WCF与其通信

    当我启动第二个进程时,我传递给