【发布时间】:2013-11-30 01:48:44
【问题描述】:
我刚刚阅读了有关在 C# 5.0 中使用 await 和 async 关键字处理异步函数的新方法。来自C# reference on await的示例:
private async Task SumPageSizesAsync()
{
// To use the HttpClient type in desktop apps, you must include a using directive and add a
// reference for the System.Net.Http namespace.
HttpClient client = new HttpClient();
// . . .
Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
byte[] urlContents = await getContentsTask;
// Equivalently, now that you see how it works, you can write the same thing in a single line.
//byte[] urlContents = await client.GetByteArrayAsync(url);
// . . .
}
Task<byte[]> 表示将生成 byte[] 类型值的异步任务的未来。在Task 上使用关键字await 基本上会将函数的其余部分放在一个延续中,该延续将在任务完成时调用。任何使用await 的函数都必须使用关键字async 并具有Task<a> 类型,如果它会返回类型a。
所以线条
byte[] urlContents = await getContentsTask;
// Do something with urlContents
会翻译成类似的东西
Task newTask = getContentsTask.registerContinuation(
byte[] urlContents => {
// Do something with urlContents
});
return newTask;
这感觉很像 Monad(-transformer?)。感觉应该 与 CPS monad 有一些关系,但可能不是。
这是我编写相应 Haskell 类型的尝试
-- The monad that async functions should run in
instance Monad Async
-- The same as the the C# keyword
await :: Async (Task a) -> Async a
-- Returns the current Task, should wrap what corresponds to
-- a async method in C#.
asyncFunction :: Async a -> Async (Task a)
-- Corresponds to the method Task.Run()
taskRun :: a -> Task a
以及上面例子的粗略翻译
instance MonadIO Async -- Needed for this example
sumPageSizesAsync :: Async (Task ())
sumPageSizesAsync = asyncFunction $ do
client <- liftIO newHttpClient
-- client :: HttpClient
-- ...
getContentsTask <- getByteArrayAsync client url
-- getContentsTask :: Task [byte]
urlContents <- await getContentsTask
-- urlContents :: [byte]
-- ...
这会是 Haskell 中的对应类型吗?是否有任何 Haskell 库以这种方式(或类似方式)实现处理异步函数/动作的方式?
另外:你能用 CPS-transformer 构建这个吗?
编辑
是的,Control.Concurrent.Async 模块确实解决了类似的问题(并且具有类似的界面),但以完全不同的方式解决了问题。我猜Control.Monad.Task 会更接近。我正在寻找的(我认为)是 Futures 的一元接口在幕后使用延续传递样式。
【问题讨论】:
-
您可以查看 haskel 库
async它应该提供您正在寻找的内容:hackage.haskell.org/package/async -
async包甚至比 C# 功能更好,因为它消除了与被调用函数真正异步的责任。我能看到的唯一缺点是性能,因为Control.Concurrent.Async(可能)比 C# 中更简单的解决方案需要更多的簿记。与美化的回调相比,轻量级线程和 STM 非常重。
标签: c# haskell asynchronous