Что такое правильная реализация интерфейса IAsyncResult? - PullRequest
13 голосов
/ 18 мая 2009

Я рассматриваю возможность добавления некоторой гибкости к созданному мною классу, который устанавливает соединение с удаленным хостом, а затем выполняет обмен информацией (рукопожатие). Текущая реализация предоставляет функцию Connect, которая устанавливает соединение, а затем блокирует ожидание на ManualResetEvent, пока обе стороны не завершили рукопожатие.

Вот пример того, как выглядит мой класс:

// create a new client instance
ClientClass cc = new ClientClass("address of host");
bool success = cc.Connect();  // will block here until the
                              //  handshake is complete
if(success)
{

}

.. и вот упрощенное высокоуровневое представление о том, что класс делает внутри:

class ClientClass
{
    string _hostAddress;
    ManualResetEvent _hanshakeCompleted;
    bool _connectionSuccess;

    public ClientClass(string hostAddress)
    {
        _hostAddress = hostAddress;            
    }

    public bool Connect()
    {
        _hanshakeCompleted = new ManualResetEvent(false);            
        _connectionSuccess = false;

        // start an asynchronous operation to connect
        //  ...
        //  ...

        // then wait here for the connection and
        //  then handshake to complete
        _hanshakeCompleted.WaitOne();

        // the _connectionStatus will be TRUE only if the
        //  connection and handshake were successful
        return _connectionSuccess;
    }

    // ... other internal private methods here
    // which handle the handshaking and which call
    // HandshakeComplete at the end

    private void HandshakeComplete()
    {
        _connectionSuccess = true;
        _hanshakeCompleted.Set();
    }
}

Я рассматриваю реализацию .NET Classic Async Pattern для этого класса. При этом я бы предоставил функции BeginConnect и EndConnect и позволил бы пользователям класса писать код следующим образом:

ClientClass cc = new ClientClass("address of host");
cc.BeginConnect(new AsyncCallback(ConnectCompleted), cc);
// continue without blocking to this line

// ..

void ConnectCompleted(IAsyncResult ar)
{
    ClientClass cc = ar.AyncState as ClientClass;
    try{
        bool success = cc.EndConnect(ar);
        if(success)
        {
             // do more stuff with the 
             //  connected Client Class object
        }
    }
    catch{
    }
}

Чтобы иметь возможность предоставить этот API, мне нужно создать класс, который реализует интерфейс IAsyncResult, который будет возвращен функцией BeginConnect и передан в функцию EndConnect соответственно.

Теперь мой вопрос: как правильно реализовать интерфейс IAsyncResult в классе?

Одним из очевидных решений было бы создание делегата с совпадающей подписью для функции Connect, а затем асинхронный вызов этого делегата с использованием BeginInvoke - EndInvoke, но это не то, что я ищу (это не очень эффективно).

У меня есть приблизительное представление о том, как я могу это сделать, но после того, как заглянул внутрь .NET Framework, как они реализуют этот шаблон в некоторых местах, я подумал, что было бы разумно спросить и посмотреть, сделал ли кто-нибудь это успешно, и если да, то На какие проблемные области следует обратить особое внимание.

Спасибо!

Ответы [ 2 ]

1 голос
/ 16 мая 2012

У вас также есть много реализаций в BCL (например, System.Runtime.Remoting.Messaging.AsyncResult) - используйте отражатель или опорный источник, чтобы проверить их.

1 голос
/ 15 июня 2009

Вы можете заключить вызов в реализацию IAsyncResult. Поскольку в последнее время я смотрел на многопоточность, я написал об этом здесь (там есть ссылки на другие реализации интерфейса):

http://msmvps.com/blogs/luisabreu/archive/2009/06/15/multithreading-implementing-the-iasyncresult-interface.aspx

...