对长期运行的基于时间的流程进行编程

发布于 2024-09-11 00:47:37 字数 923 浏览 6 评论 0原文

我想知道编写应用程序的最佳方法是什么。基本上,我有一个多线程的运动模拟项目,可以同时执行不同的游戏模拟。

我将匹配项存储在 SQLite 数据库中,该数据库附加了日期时间。

我想编写一个应用程序,每隔一小时左右检查一次,看看是否需要播放任何新比赛并关闭这些线程。

我不能依赖任务调度程序每小时执行一次,因为该进程的不同实例会共享一些对象(特别是锦标赛对象),我怀疑这些对象在保存回数据库时会被较新的进程覆盖。因此,理想情况下,我需要编写某种长时间运行的进程,在几个小时之间休眠。

我已经编写了对象模型,以便每个对象仅从内存加载一次,因此只要所有模拟线程都是从该应用程序生成的,它们就不应该覆盖数据。

编辑:有关要求的更多详细信息

基本上,多个比赛需要能够同时运行。这些匹配可以是任意长度,因此没有必要一个在另一个开始之前完成(事实上,在大多数情况下,会有多个匹配同时执行)。

我设想的是一个在后台运行的程序(我猜是一个服务?),它会休眠 60 分钟,然后检查数据库以查看是否应该启动任何游戏。如果有任何要启动的游戏,它会启动线程来模拟这些游戏,然后返回睡眠状态。因此,模拟线程正在运行,但“调度”线程又休眠了 60 分钟。

我不能(我认为)使用默认的操作系统任务调度接口的原因是,这些接口需要将要执行的任务作为新进程来拒绝。我开发了我的数据库对象模型,以便在第一次加载(内存引用)时由每个对象类缓存它们,这意味着每个对象仅从内存加载一次,并且该引用用于所有保存。这意味着当每个模拟线程完成并保存其状态时,将使用相同的引用(具有更新的状态)来保存状态。如果每次启动不同的可执行文件,则每个进程可能会打开不同的内存引用,因此一个进程可以保存到数据库中并覆盖另一进程写入的状态。

服务看起来是一条出路。有没有办法让服务休眠 60 分钟,然后唤醒并执行函数?我觉得将其作为标准控制台应用程序会浪费内存,但我不知道是否有一种有效的方法可以做到这一点,而我不知道。

I was wondering what the best way to write an application would be. Basically, I have a sports simulation project that is multi-threaded and can execute different game simulations concurrently.

I store my matches in a SQLite database that have a DateTime attached to it.

I want to write an application that checks every hour or so to see if any new matches need to be played and spawns those threads off.

I can't rely on the task scheduler to execute this every hour because there are objects that the different instances of that process would share (specifically a tournament object), that I suspect would be overwritten by a newer process when saved back into the DB. So ideally I need to write some sort of long-running process that sleeps between hours.

I've written my object model so that each object is only loaded once from memory, so as long as all simulation threads are spawned from this one application, they shouldn't be overwriting data.

EDIT: More detail on requirements

Basically, multiple matches need to be able to run concurrently. These matches can be of arbitrary length, so it's not necessary that one finishes before the other begins (in fact, in most cases there will be multiple matches executing at the same time).

What I'm envisioning is a program that runs in the background (a service, I guess?) that sleeps for 60 minutes and then checks the database to see if any games should be started. If there are any to be started, it fires off threads to simulate those games and then goes back to sleep. Hence, the simulation threads are running but the "scheduling" thread is sleeping for another 60 minutes.

The reason I can't (I think) use the default OS task-scheduling interface is that these require the task to be executed to be spurned as a new process. I have developed my database object model such that they are cached by each object class on first load (the memory reference) meaning that each object is only loaded from memory once and that reference is used on all saves. Meaning that when each simulation thread is done and saves off its state, the same reference is used (with updated state) to save off the state. If a different executable is launched every time, presumably a different memory reference will be opened by each process and hence one process could save into the DB and overwrite the state written by the other process.

A service looks like the way to go. Is there a way to make a service just sleep for 60 minutes and wake up and execute a function after that? I feel like making this a standard console application would waste memory, but I don't know if there is an efficient way to do that which I'm not aware of.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小情绪 2024-09-18 00:47:37

如果你想让它真正可靠,就把它变成一个服务。

但我认为将其作为普通(控制台、WinForms、WPF)应用程序没有任何问题。

也许您可以稍微扩展一下要求。

If you want to make it really reliable, make it a Service.

But I don't see any problems in making it a normal (Console, WinForms, WPF) application.

Maybe you could expand on the requirements a little.

绮筵 2024-09-18 00:47:37

我不能(我认为)使用默认的操作系统任务调度接口的原因是,这些接口需要将要执行的任务作为新进程来拒绝。我开发了我的数据库对象模型,以便它们在第一次加载(内存引用)时由每个对象类缓存,这意味着每个对象仅从内存加载一次,并且该引用用于所有保存

如果您希望所有内容永远保持缓存) ,那么您确实需要一个可以永远运行的应用程序。您可以将其设为 Windows 服务或普通 Windows 应用程序。
Windows服务只是一个符合服务管理器API的普通exe。如果您想制作一个,Visual Studio 有一个向导,可以为您自动生成一些框架代码。基本上,您没有 Main 方法,而是使用带有 Run 方法的 Service 类,其他所有内容都是相同的。

如果您愿意,您可以使用 Windows 任务计划程序来安排您的操作。执行此操作的方法是让长时间运行的 Windows 服务在后台不执行任何操作。让它打开一个 TCP 套接字或命名管道或其他东西,然后就坐在那里。然后编写一个小的“存根”exe,它仅连接到此套接字或命名管道并告诉后台应用程序唤醒。
当然,这比在后台应用程序中执行睡眠要困难得多,但它确实让您拥有更多控制权 - 您可以更改睡眠时间而无需重新启动后台服务,运行它是按需的,等等。


不过,我会考虑你的设计。事实上,您依赖于长期运行的服务是一个很大的故障点。如果您的应用程序需要运行数天,并且有一个错误导致其崩溃,那么您必须重新开始。一种更好的架构是遵循 Unix 模型,其中有一些小进程,它们启动,做一件事,然后完成(在这种情况下,将每个游戏模拟作为它自己的进程进行处理,因此如果一个进程死亡,它不会占用主进程或其他模拟)。

您尝试让它长时间运行的主要原因似乎是缓存数据库查询。您真的需要这样做吗?很多时候数据库足够快(它们有自己的缓存,非常智能)。我见过程序员犯的一个常见错误是假设数据库之类的东西很慢,并浪费大量时间进行优化,而实际上它会很好

The reason I can't (I think) use the default OS task-scheduling interface is that these require the task to be executed to be spurned as a new process. I have developed my database object model such that they are cached by each object class on first load (the memory reference) meaning that each object is only loaded from memory once and that reference is used on all saves

If you want everything to remain cached forever, then you do need to have an application that simply runs forever. You can make this a windows service, or a normal windows application.
A windows service is just a normal exe that conforms to the service manager API. If you want to make one, visual studio has a wizard which auto-generates some skeleton code for you. Basically instead of having a Main method you have a Service class with a Run method and everything else is the same.

You could, if you wanted to, use the windows task scheduler to schedule your actions. The way you'd do this is to have your long-running windows service in the background that does nothing. Have it open a TCP socket or named pipe or something and just sit there. Then write a small "stub" exe which just connects to this socket or named pipe and tells the background app to wake up.
This is, of course, a lot harder than just doing a sleep in your background application, but it does let you have a lot more control - you can change the sleep time without restarting the background service, run it on-demand, etc.


I would however, consider your design. The fact that you rely on a long-running service is a large point of failure. If your app needs to run for days, and you have a single bug which crashes it, then you have to start again. A much better architecture is to follow the Unix model, where you have small processes which start, do one thing, then finish (in this case, process each game simulation as it's own process so if one dies it doesn't take the master process or the other simulations down).

It seems like the main reason you're trying to have it long-running is to cache your database queries. Do you actually need to do this at all? A lot of the time databases are plenty fast enough (they have their own caches, which are plenty smart). A common mistake I've seen programmers make is to just assume that something like a database is slow, and waste a pile of time optimizing when in actual fact it would be fine

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文