Как выполнять цепные обратные вызовы в F #?
В С# я использую асинхронные версии 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);
}
Мой вопрос в том, как я смоделирую нечто подобное в 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()
}
Вышеприведенный код не работает, потому что accept не определен, а его рекурсивная техническая маркировка неверна, поскольку это не рекурсивный метод?
Ответы
Ответ 1
Я не уверен, что вы подразумеваете под словом "это не приемный метод"; если вы ссылаетесь на функцию из собственного определения, то это рекурсивная функция. У меня нет большого опыта работы с классами Sockets, но, возможно, что-то в этом роде - это то, что вы ищете?
let rec accept(t : TcpListener) =
async {
let! client = t.AsyncAcceptTcpClient()
// do some stuff with client here
do! accept(t)
}
Ответ 2
@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
}
(это был код ввода в мой браузер, надеюсь, он компилируется). Это хорошо, поскольку вы, конечно, не можете использовать цикл в коде С# (который должен охватывать несколько методов с помощью обратных вызовов начала и конца).