Какой способ предпочтительнее при выполнении асинхронных вызовов WCF?

При вызове службы WCF асинхронной, кажется, есть два способа сделать это.

1.

WcfClient _client = new WcfClient();    
public void One()
{
    _client.BegindoSearch("input", ResultOne, null);
}

private void ResultOne(IAsyncResult ar)
{
    string data = _client.EnddoSearch(ar);
}

2.

public void Two()
{
    WcfClient client = new WcfClient();
    client.doSearchCompleted += TwoCompleted;
    client.doSearchAsync("input");
}

void TwoCompleted(object sender, doSearchCompletedEventArgs e)
{
    string data = e.Result;
}

И с новым Task<T> класс у нас есть простой третий способ, заключив синхронную операцию в задачу.

3.

public void Three()
{
    WcfClient client = new WcfClient();
    var task = Task<string>.Factory.StartNew(() => client.doSearch("input"));
    string data = task.Result;
}

Все они дают вам возможность выполнять другой код, пока вы ждете результата, но я думаю, Task<T> дает лучший контроль над тем, что вы выполняете до или после получения результата.

Есть ли преимущества или недостатки использования одного над другим? Или сценарии, где один из способов сделать это предпочтительнее?

2 ответа

Решение

Я бы не использовал окончательную версию, потому что она будет запускать операцию в рабочем потоке вместо потока ввода-вывода. Это особенно плохо, если вы делаете это внутри ASP.NET, где рабочие потоки необходимы для обслуживания запросов. Не говоря уже о том, что вы по-прежнему блокируете основной поток, ожидая завершения задачи при проверке ее ResultТаким образом, технически вы тратите два рабочих потока, или один рабочий и пользовательский интерфейс.

BeginXYZ а также XyzAsync методы для клиентов WCF работают в основном одинаково - вы должны выбрать подходящую версию в зависимости от варианта использования, который вы хотите поддерживать (либо APC, либо управляемый событиями соответственно). Например, BeginXyz версию (возможно, нелогично) будет проще использовать на асинхронной странице ASP.NET (или MVC), тогда как XyzAsync версия будет проще использовать в форме Windows.

Есть проблема с вашим первым примером. Вы, конечно, не должны создавать новый экземпляр WcfClient при вызове EndDoSearch. Вы должны либо сохранить исходный экземпляр в поле, либо передать его в качестве параметра состояния.

Но в целом я предпочитаю вариант № 1, потому что он позволяет очень легко использовать анонимный метод для обработки результата.

var client = new WcfClient();
client.BeginDoSearch("input", ar => {

    var result = client.EndDoSearch(ar);
    // blah blah

}, null);
Другие вопросы по тегам