如何在F#中进行链式回调?

esa*_*sac 2 f# asynchronous tcplistener

在C#中,我使用的是TcpListener/TcpClient的异步版本,我通过回调方法链接这些,以便在回调完成时发布另一个Accept/Read.这是一个例子(未经测试):

    public void Start()
    {
        TcpListener listener = new TcpListener(IPAddress.Any, 3000);
        listener.Start();

        PostAccept(listener);
    }

    private void PostAccept(TcpListener listener)
    {
        listener.BeginAcceptTcpClient(AcceptCallback, listener);
    }

    private void AcceptCallback(IAsyncResult ar)
    {
        var listener = ar.AsyncState as TcpListener;

        if (listener == null)
        {
            return;
        }

        // get the TcpClient and begin a read chain in a similar manner

        PostAccept(listener);
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是如何在F#中建模类似的东西?我会使用async关键字吗?BeginAcceptTcpClient,BeginRead等之后的代码本质上是将在回调函数中执行的代码吗?例如,这是正确的吗?

let accept(listener:TcpListener) = async {      
  let! client = listener.AsyncAcceptTcpClient()    
  // do something with the TcpClient such as beginning a Read chain
  accept(listener)
  return()
}    
Run Code Online (Sandbox Code Playgroud)

上面的代码不起作用,因为未定义accept,并且在技术上标记它是不正确的,因为它不是递归方法?

Bri*_*ian 5

@kvb的答案是正确和惯用的.

只想指出你可以使用(喘气)一个循环:

let accept(t:TcpListener) =
    let completed = ref false 
    async {
        while not(!completed) do 
            let! client = t.AsyncAcceptTcpClient()
            if client <> null then
                Blah(client)
            else
                completed := true
    }
Run Code Online (Sandbox Code Playgroud)

(这是在我的浏览器中键入代码,希望它编译).这很好,因为你当然不能在C#代码中使用循环(必须跨越多个方法使用开始/结束回调).