如何手动杀死线程?

时间:2018-10-10 16:29:56

标签: haskell

我正在 SELECT c.name , s.date , s.score FROM country c LEFT JOIN score s ON s.country_id = c.id LEFT JOIN ( SELECT o.country_id , o.date , MAX(o.score) AS max_date_score FROM ( SELECT m.country_id , MAX(m.date) AS max_date FROM score m GROUP BY m.country_id ) n JOIN score o ON o.country_id = n.country_id AND o.date = n.max_date GROUP BY o.country_id , o.date ) p ON p.country_id = c.id ORDER BY p.date DESC , p.max_date_score DESC , c.name ASC , s.date ASC , s.score DESC 中测试一些分叉线程的函数,有点像这样:

ghci

结果是:

myForkingFunction = do
  tid <- forkIO (workerFunction)
  putStrLn ("Worker thread: " ++ show tid)
  putStrLn ("...lots of other actions...")

  where workerFunction = do 
          putStrLn "In real life I'm listening for jobs...."
          workerFunction

(依此类推)

然后,当我 > myForkingFunction Worker thread: ThreadId 216 ...lots of other actions... > In real life I'm listening for jobs.... In real life I'm listening for jobs.... In real life I'm listening for jobs.... In real life I'm listening for jobs.... 遍历代码时,我注意到即使重新加载,我的:r仍在运行。

因此,我认为可以只看打印输出并执行workerFunction或其他任何操作。

但是首先,我需要从killThread (ThreadId 234)导入ThreadId(..)吗?

然后我得到这个错误:

GHC.Conc.Sync

所以我认为我一定要解决这个错误?

4 个答案:

答案 0 :(得分:4)

我认为没有任何方法可以构建ThreadId(例如,根据show的结果)。请参见this question,因此您需要保留ThreadId返回的forkIO,例如通过将功能更改为:

myForkingFunction = do
  tid <- forkIO (workerFunction)
  putStrLn ("Worker thread: " ++ show tid)
  putStrLn ("...lots of other actions...")
  return tid

并在ghci中做

> tid <- myForkingFunction
> killThread tid

您得到的错误有点令人困惑,我认为这与数字文字(例如216)是多态的有关; ThreadId的参数是ThreadId#,它是未提升的类型,因此您可以在编译器甚至抱怨“没有实例Num ThreadId#”之前看到错误,

答案 1 :(得分:4)

ThreadId值由运行时特别处理。您不能只创建一个。创建线程时,您需要访问ThreadId或由线程内部的forkIO生成的myThreadId

只是为了获得额外的乐趣,当线程中的任何ThreadId仍然可以访问时,线程不会被垃圾收集。因此,如果需要它们,您不能仅仅坚持使用它们。您实际上需要制定一个计划来管理线程。

我认为最好使用async library,它是各种链接操作,以确保当杀死父线程时,它也杀死所有子线程。这有点(或很多)笨拙的代码样式,但这是获得正确行为的最佳方法。

答案 2 :(得分:3)

ThreadId实际上不是数字,尽管它具有与之相关的数字以供识别。 ThreadIdThreadId#的包装,它是指向线程状态对象(TSO或RTS代码为StgTSO)的指针。该对象包含有关线程的所有实际内部信息。无法将Int转换为ThreadId(我很确定运行时系统甚至不维护从线程ID号到ThreadId#的映射,并且肯定有没有primop支持这种转换),因此您现在就可以放弃。 killThreadthrowTo线程的唯一方法是坚持使用ThreadId给您的forkIO。请注意,杀死线程通常不是您想要停止它的方法。通常,您想通过通过MVar与之通信来进行更多控制。大多数人使用async库中的工具来管理并发。

答案 3 :(得分:-5)

问题在于killThread的参数是错误的。您需要写killThread 234而不是killThread (ThreadId 234)。你尝试过吗?