Как перезапустить задачу элегантно? - PullRequest
2 голосов
/ 01 октября 2011

Итак, у меня есть что-то вроде этого:

Task.Factory.FromAsync<TcpClient>(tcpListener.BeginAcceptTcpClient, tcpListener.EndAcceptTcpClient, tcpListener).ContinueWith(ConnectionAccepted);

private void ConnectionAccepted(Task<TcpClient> tcpClientTask)
{
    TcpClient tcpClient = tcpClientTask.Result;

    // Do something with tcpClient
}

Теперь мне интересно, как я могу снова запустить Task.Factory.FromAsync<TcpClient>(...) в конце этого метода?Я не могу просто скопировать и вставить строку кода, потому что у меня нет доступа к TcpListener и я бы не стал делать его переменной-членом.Даже если бы я это сделал, это такая длинная строка кода, что для меня это похоже на дублирование кода.

Предоставляет ли структура задач какой-то механизм для достижения этой цели?1012 *

Ответы [ 2 ]

2 голосов
/ 01 октября 2011

Как предложил svick, самый простой способ - ввести tcpListener в поле.Но если по какой-то причине вы не можете этого сделать, попробуйте этот шаблон:

void AcceptClient()
{
    // Create tcpListener here.
    AcceptClientImpl(tcpListener);
}

void AcceptClientImpl(TcpListener tcpListener)
{
    Task.Factory.FromAsync<TcpClient>(tcpListener.BeginAcceptTcpClient, tcpListener.EndAcceptTcpClient, tcpListener).ContinueWith(antecedent =>
    {
        ConnectionAccepted(antecedent.Result);

        // Restart task by calling AcceptClientImpl "recursively".
        // Note, this is called from the thread pool. So no stack overflows.
        AcceptClientImpl(tcpListener);
    });
}

void ConnectionAccepted(TcpClient tcpClient)
{
    // Do stuff here.
}
1 голос
/ 01 октября 2011

Не думаю, что в Framework есть что-то для перезапуска Task s.

Но вашу проблему можно решить тривиально, поместив tcpListener в поле и поместив строку, которая создает задачу, в метод, чтобы не было дублирования кода.

...