Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which way is preferred when doing asynchronous WCF calls?

When invoking a WCF service asynchronous there seems to be two ways it can be done.

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

And with the new Task<T> class we have an easy third way by wrapping the synchronous operation in a task.

3.

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

They all give you the ability to execute other code while you wait for the result, but I think Task<T> gives better control on what you execute before or after the result is retrieved.

Are there any advantages or disadvantages to using one over the other? Or scenarios where one way of doing it is more preferable?

like image 549
Mikael Svenson Avatar asked Apr 10 '10 20:04

Mikael Svenson


2 Answers

I would not use the final version because it will run the operation on a worker thread instead of an I/O thread. This is especially bad if you're doing it inside ASP.NET, where the worker threads are needed to serve requests. Not to mention, you're still blocking on the main thread waiting for the task to finish when you check its Result, so technically you're wasting two worker threads, or one worker and the UI.

The BeginXYZ and XyzAsync methods for WCF clients work essentially the same way - you should choose the appropriate version based on the use case you want to support (either APC or event-driven, respectively). For example, the BeginXyz version would (perhaps counterintuitively) be easier to use within an ASP.NET (or MVC) async page, whereas the XyzAsync version would be easier to use in a Windows Form.

like image 53
Aaronaught Avatar answered Oct 12 '22 23:10

Aaronaught


There's a problem with your first example. You should certainly not be creating a new WcfClient instance when you call EndDoSearch. You should either keep the original instance around in a field or pass it as the state parameter.

But in general, I prefer option #1 because it makes it very easy to use an anonymous method to handle the result.

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

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

}, null);
like image 20
Josh Avatar answered Oct 13 '22 01:10

Josh