How to use Visual Studio - generated async WCF calls?

14,217

Solution 1

If you select 'Generate asynchrounous operations', you will get the 'old' behavior where you have to use callbacks.

If you want to use the new async/await syntax, you will have to select 'Generate task-based operations' (which is selected by default).

When using the default Wcf template, this will generate the following proxy code:

  public System.Threading.Tasks.Task<string> GetDataAsync(int value) {
      return base.Channel.GetDataAsync(value);
  }

As you can see, there are no more callbacks. Instead a Task<T> is returned.

You can use this proxy in the following way:

public static async Task Foo()
{
    using (ServiceReference1.Service1Client client = new ServiceReference1.Service1Client())
    {
        Task<string> t = client.GetDataAsync(1);
        string result = await t;
    }
}

You should mark the calling method with async and then use await when calling your service method.

Solution 2

Your Service Reference can (if you are using .Net 4.5) be set to generate task-based async calls. (Configure Service Reference > check Allow generation of asynchronous operations > select Generate task-based operations) These can be used like any async method. Here's an example of how to use it:

using (var proxy = new YourServiceClient())
{
    var t1 = proxy.GetMessagesAsync();
    var t2 = proxy.GetMessagesAsync();
    //they're runnning asynchronously now!

    //let's wait for the results:
    Task.WaitAll(t1, t2);
    var result1 = t1.Result;
    var result2 = t2.Result;
    Console.WriteLine(result1);
    Console.WriteLine(result2);
}

If your client is not using .Net 4.5, you cannot generate service references that use async. You'll have to do it the old fashioned way, using callbacks. Here's an example:

static void m()
{
    var proxy = new YourServiceClient();
    proxy.GetMessagesCompleted += proxy_GetMessagesCompleted;
    proxy.GetMessagesAsync();
}

static void proxy_GetMessagesCompleted(object sender, GetMessagesCompletedEventArgs e)
{
    var proxy = (IDisposable)sender;
    proxy.Dispose(); //actual code to close properly is more complex

    if (e.Error != null)
    {
        // do something about this
    }

    var result = e.Result;
    Console.WriteLine(result);
}

Note that in actual code for either of these scenarios, you shouldn't use using or IDisposable.Dispose() to clean up the client, see Avoiding Problems with the Using Statement and this code to get you started into the confusing world of closing these things.

Solution 3

If you're on VS2012, then you can use the *Async calls like this:

var proxy = new MyClient();
var result = await proxy.GetMessagesAsync();
Share:
14,217
pmichna
Author by

pmichna

Software developer

Updated on June 04, 2022

Comments

  • pmichna
    pmichna almost 2 years

    My OperationContract:

    public List<MessageDTO> GetMessages()
            {
                List<MessageDTO> messages = new List<MessageDTO>();
                foreach (Message m in _context.Messages.ToList())
                {
                    messages.Add(new MessageDTO()
                    {
                        MessageID = m.MessageID,
                        Content = m.Content,
                        Date = m.Date,
                        HasAttachments = m.HasAttachments,
                        MailingListID = (int)m.MailingListID,
                        SenderID = (int)m.SenderID,
                        Subject = m.Subject
                    });
                }
                return messages;
            }
    

    In Service Reference configuration I checked the option "Generate asynchronous operations". How do I use the generated GetMessagesAsync()? In the net I found examples that use AsyncCallback, however I'm not familiar with that. Is there a way to use it in some friendly way like async and await keywords in .NET 4.5? If not, what should I do to invoke the method asynchronously?