【问题标题】:PostAndReply on a disposed MailboxProcessorPostAndReply 在已处理的 MailboxProcessor 上
【发布时间】:2013-08-19 11:45:24
【问题描述】:

是否可以让 PostAndAsyncReply 在其 MailboxProcessor 被释放(或以其他方式停止)时立即返回?或者是否有一些关于如何安全使用 PostAndReply 方法而不产生死锁的“模式”/最佳实践?

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

  [<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 在被处理时如何反应。不需要处理吗?

【问题讨论】:

    标签: f# mailboxprocessor


    【解决方案1】:

    没有内置支持取消挂起的PostAndReply 调用,但您可以实现这一点。如需处理处置,您可以将邮箱正文包裹在try .. finally中。在finally 块中,您可以通过某种方式发出邮箱处理器已停止的信号。以下使用取消令牌源:

    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
    

    有两点需要牢记:

      1234563
    • 最后我不得不使用StartAsTask 而不是RunSynchronously 来启动任务。出于某种原因(不太确定),使用RunSynchronously 似乎不会取消计算。

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

    要回答您有关Dispose 的问题,我不完全确定行为是什么,但处置邮箱处理器会处置内部AutoResetEvent(请参阅the source code),用于表示消息已到达.我想这只是意味着邮箱处理器不会再接受任何消息。

    【讨论】:

      猜你喜欢
      • 2019-06-08
      • 1970-01-01
      • 1970-01-01
      • 2012-01-03
      • 1970-01-01
      • 1970-01-01
      • 2013-04-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多