首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >已处置的PostAndReply上的MailboxProcessor

已处置的PostAndReply上的MailboxProcessor
EN

Stack Overflow用户
提问于 2013-08-19 11:45:24
回答 1查看 695关注 0票数 6

当PostAndAsyncReply的MailboxProcessor被释放(或以其他方式停止)时,是否有可能使其立即返回?或者,对于如何在不创建死锁的情况下安全地使用PostAndReply方法,有什么“模式”/最佳实践吗?

现在,我遇到的问题是,当PostAndAsyncReply被释放时,MailboxProcessor永远不会返回。使用超时值参数不是一个选项,因为我不能等待(此外,选择合理的超时非常困难或不可能,因为这取决于太多的因素)。

代码语言:javascript
复制
  [<Test>]
  let ``waiting for a reply from a disposed agent``() =
    use server = MailboxProcessor.Start(fun inbox -> async {
      ()
    })

    (server :> System.IDisposable).Dispose()

    server.PostAndReply (fun reply -> reply) // <- deadlock
    |> ignore)

编辑:我见过的关于MailboxProcessors的大多数例子(包括。(MSDN上的那些)甚至不介意处理MailboxProcessors。而且MSDN没有解释MailboxProcessors在被释放时是如何反应的。难道没有必要处理它们吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-19 13:23:59

对于取消挂起的PostAndReply调用,没有内置的支持,但是您可以实现这一点。若要处理处理,可以在try .. finally中包装邮箱正文。在finally块中,可以以某种方式向邮箱处理器发出停止的信号。以下内容使用取消令牌源进行此操作:

代码语言:javascript
复制
let disposed = new System.Threading.CancellationTokenSource()
let server = MailboxProcessor<AsyncReplyChannel<obj>>.Start(fun inbox -> 
  async { 
    try 
      // The normal body of the mailbox processor goes here
      do! Async.Sleep(1000)
      printfn "done"
    finally 
      // Cancel all pending calls post and reply
      disposed.Cancel()
   })

// Dispose the mailbox processor    
(server :> System.IDisposable).Dispose()

// When sending message, we use 'StartAsTask' and set a cancellation token,
// so that the work is stopped when the mailbox processor finishes
let wait = server.PostAndAsyncReply(fun reply -> reply)
let task = Async.StartAsTask(wait, cancellationToken = disposed.Token)
printfn "%A" task.Result

有两件事要记住:

  • 如果邮箱处理器正在运行一些长时间运行的工作(比如上面的睡眠),那么处理将在完成之后发生(这是因为异步工作流的性质--它们不强制取消计算)。
  • 最后,我不得不使用StartAsTask而不是RunSynchronously来启动任务。由于某些原因(不太确定),使用RunSynchronously似乎不会取消计算。

您可以轻松地将其封装在内部使用MailboxProcessor的类中,公开类似的接口并添加此功能--但这对于单个答案来说有点太过了!

要回答您关于Dispose的问题,我不完全确定行为是什么,但是处理邮箱处理器会释放一个内部AutoResetEvent (参见源代码),该内部AutoResetEvent用来表示消息已经到达。我认为这只是意味着邮箱处理器将不再接受任何进一步的消息。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18312987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档