How to do chained callbacks in F#?

烈酒焚心 提交于 2019-12-21 05:54:07

问题


In C# I am using the asynchronous versions of TcpListener/TcpClient, and I am chaining these via the callback method so that another Accept/Read is posted when the callback completes. Here is an example (untested):

    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);
    }

My question is how do I model something similar in F#? Would I use the async keyword? Is the code after BeginAcceptTcpClient, BeginRead, etc.. essentially the code that would be executed in the callback function? For example, is this correct?

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

The above code doesn't work because accept isn't defined, and marking it recursive technically isn't true as it isn't a recursive method?


回答1:


I'm not sure what you mean by "it isn't a recusive method"; if you refer to a function from within its own definition, then it is a recursive function. I don't have much experience with the Sockets classes, but perhaps something along these lines is what you're looking for?

let rec accept(t : TcpListener) =
  async {
    let! client = t.AsyncAcceptTcpClient()

    // do some stuff with client here

    do! accept(t)
  }



回答2:


@kvb's answer is correct and idiomatic.

Just wanted to also point out you can use (gasp) a loop:

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
    }

(that was typing code into my browser, hopefully it compiles). Which is nice, since you certainly can't use a loop in the C# code (that has to span multiple methods with the begin/end callbacks).



来源:https://stackoverflow.com/questions/1468145/how-to-do-chained-callbacks-in-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!