同时等待Haskell中的两个输入

同时等待Haskell中的两个输入,haskell,concurrency,io,Haskell,Concurrency,Io,标题可能有点模糊。这就是我的意思: 假设我有两种方法来获取程序的输入。第一种是通过键盘,使用函数getLine,直到读取一行为止。另一种是,例如,通过TChan,其中使用readTChan chan也将导致一个块,直到通道中存在一个值,然后将读取该值 我想要完成的是能够使用单个线程等待两个值,并且不允许CPU跳到100%。当两个值中的一个可用时,将获取该值并继续程序。(例如,使用或通知接收到两个值中的哪一个。) 这可能吗 多谢各位 我认为“使用单个线程”在这里没有意义。您必须已经使用多个Hask

标题可能有点模糊。这就是我的意思:

假设我有两种方法来获取程序的输入。第一种是通过键盘,使用函数
getLine
,直到读取一行为止。另一种是,例如,通过
TChan
,其中使用
readTChan chan
也将导致一个块,直到通道中存在一个值,然后将读取该值

我想要完成的是能够使用单个线程等待两个值,并且不允许CPU跳到100%。当两个值中的一个可用时,将获取该值并继续程序。(例如,使用
通知接收到两个值中的哪一个。)

这可能吗

多谢各位

我认为“使用单个线程”在这里没有意义。您必须已经使用多个Haskell线程来写入
TChan
。您应该使用两个Haskell线程来执行此操作,并使用
MVar
或类似工具来传递第一个到达的结果。例如:

module Main where

import System.IO
import Control.Concurrent
import Control.Concurrent.MVar
import Control.Concurrent.STM
import Control.Concurrent.STM.TChan

main = do
   chan <- newTChanIO
   forkIO (threadTChanWrite chan)
   threadMultiplexedRead chan

threadTChanWrite chan = do
   threadDelay 5000000
   atomically $ writeTChan chan 3

threadMultiplexedRead chan = do
   mvar <- newEmptyMVar
   forkIO (threadKeyboardRead mvar)
   forkIO (threadTChanRead mvar chan)
   v <- readMVar mvar
   print v

threadKeyboardRead mvar = do
   str <- getLine
   putMVar mvar (Right str)

threadTChanRead mvar chan = do
   v <- atomically (readTChan chan)
   putMVar mvar (Left v)
modulemain其中
导入系统.IO
导入控制。并发
导入控制.Concurrent.MVar
导入控制.Concurrent.STM
导入控制.Concurrent.STM.TChan
main=do
陈
我有两种方法来获取程序的输入


您应该能够使用两个线程,每个输入源一个,它们等待各自的输入,将结果写入由第三个线程控制的共享通道或mvar。

hackage上的“async”包中有
race::IO a->IO b->IO(a b)
助手函数

同时运行两个IO操作,因此一个可以是您的
getLine
,另一个可以是
MVar
上的阻塞。返回一个
,指示哪个先返回(另一个被取消)


让一个IO线程调用getLine,并将其结果也放在TChan中如何?对我来说,它应该可以工作。你到底为什么要使用一个线程?例如,如果您需要等待3个输入,该怎么办?还是5?还是10?为什么会有任意的限制?我猜你有一些代码,其中使用了多个线程,并且你有100%的CPU?您可能希望发布代码,以便其他人了解原因:正确的解决方案是线程,而这可能只是一个实现问题。@Charles您没有抓住要点。不使用多个线程是毫无意义的,而这家伙甚至没有说为什么。他不需要说为什么,我也不明白我们怎么知道这个愿望是毫无意义的。我想OP是在期待操作系统线程,而不是Haskell线程(延续)。由于Haskell线程只是两个延续,这确实是一个更好的解决方案。。。事实上,我们所有的解决方案都使用多个Haskell线程来交错IO,正如公认的答案所做的那样……在我看来,这是正确的答案。被接受的答案过于复杂,这个答案执行了被接受的答案所要求的提示。您必须有充分的理由使用
forkIO
而不是
async