简体   繁体   English

退出Haskell程序的最佳方法是什么?

[英]What's the best way to exit a Haskell program?

I've got a program which uses several threads. 我有一个使用多个线程的程序。 As I understand it, when thread 0 exits, the entire program exits, regardless of any other threads which might still be running. 据我了解,当线程0退出时,整个程序退出,无论其他线程可能仍在运行。

The thing is, these other threads may have files open. 问题是,这些其他线程可能有文件打开。 Naturally, this is wrapped in exception-handling code which cleanly closes the files in case of a problem. 当然,这包含在异常处理代码中,以便在出现问题时干净地关闭文件。 That also means that if I use killThread (which is implemented via throwTo ), the file should also be closed before the thread exits. 这也意味着如果我使用killThread (通过throwTo实现),该文件应该在线程退出之前关闭。

My question is, if I just let thread 0 exit, without attempting to stop the other threads, will all the various file handles be closed nicely? 我的问题是,如果我只是让线程0退出,而不试图阻止其他线程,那么各种文件句柄是否会被很好地关闭? Does any buffered output get flushed? 是否刷新了任何缓冲输出?

In short, can I just exit, or do I need to manually kill threads first? 简而言之,我可以退出,还是我需要先手动杀死线程?

You can use Control.Concurrent.MVar to achieve this. 您可以使用Control.Concurrent.MVar来实现此目的。 An MVar is essentially a flag which is either ''empty'' or "full". MVar本质上是一个“空”或“满”的标志。 A thread can try to read an MVar and if it is empty it blocks the thread. 一个线程可以尝试读取一个MVar ,如果它是空的,它会阻塞该线程。 Wherever you have a thread which performs file IO, create an MVar for it, and pass it that MVar as an argument. 只要你有一个执行文件IO的线程,就为它创建一个MVar ,然后将它传递给MVar作为参数。 Put all the MVar s you create into a list: 将您创建的所有MVar放入列表中:

main = do
  let mvars = sequence (replicate num_of_child_threads newEmptyMVar)
  returnVals <- sequence (zipWith (\m f -> f m) 
                                  mvars 
                                  (list_of_child_threads :: [MVar -> IO a])) 

Once a child thread has finished all file operations that you are worried about, write to the MVar . 一旦子线程完成了您担心的所有文件操作,请写入MVar Instead of writing killThread you can do 你可以做而不是编写killThread

mapM_ takeMVar mvars >> killThread 

and where-ever your thread would exit otherwise, just take all the MVar s. 而且你的线程会在哪里退出,只需要拿走所有的MVar

See the documentation on GHC concurrency for more details. 有关更多详细信息,请参阅有关GHC并发性文档

From my testing, I have discovered a few things: 从我的测试中,我发现了一些东西:

  1. exitFailure and friends only work in thread 0. (The documentation actually says so, if you go to the trouble of reading it. These functions just throw exceptions, which are silently ignored in other threads.) exitFailure和朋友只能在线程0中工作。(文档实际上是这样说的,如果你去阅读它的麻烦。这些函数只是抛出异常,在其他线程中会被忽略。)

  2. If an exception kills your thread, or your whole program, any open handles are not flushed. 如果异常终止您的线程或整个程序,则不会刷新任何打开的句柄。 This is excruciatingly annoying when you're desperately trying to figure out exactly where your program crashed! 当你拼命想弄清楚你的程序崩溃的位置时,这非常令人烦恼!

So it appears it if you want your stuff flushed before the program exits, then you have to implement this. 所以看来如果你想在程序退出之前刷新你的东西,那么必须实现它。 Just letting thread 0 die doesn't flush stuff, doesn't throw any exception, just silently terminates all threads without running exception handlers. 只是让线程0死不会刷新东西,不抛出任何异常,只是默默地终止所有线程而不运行异常处理程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM