如何使用Visual Studio生成的异步WCF调用?

时间:2012-12-08 13:04:18

标签: c# .net wcf asynchronous

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

在服务参考配置中,我选中了“生成异步操作”选项。如何使用生成的GetMessagesAsync()?在网上我找到了使用AsyncCallback的例子,但是我并不熟悉。有没有办法以一些友好的方式使用它,如.NET 4.5中的asyncawait关键字?如果没有,我该怎么做才能异步调用该方法?

4 个答案:

答案 0 :(得分:7)

如果选择“Generate asynchrounous operations”,您将获得必须使用回调的“旧”行为。

如果要使用新的async / await语法,则必须选择“生成基于任务的操作”(默认选中)。

使用默认Wcf模板时,这将生成以下代理代码:

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

正如您所看到的,没有更多的回调。而是返回Task<T>

您可以通过以下方式使用此代理:

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

您应该使用async标记调用方法,然后在调用服务方法时使用await

答案 1 :(得分:3)

您的服务参考可以(如果您使用.Net 4.5)设置为生成基于任务的异步调用。 (配置服务参考&gt;选中允许生成异步操作&gt;选择生成基于任务的操作)这些可以像任何async方法一样使用。以下是如何使用它的示例:

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

如果您的客户端未使用.Net 4.5,则无法生成使用async的服务引用。你必须使用回调的老式方式。这是一个例子:

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

请注意,在这些方案的实际代码中,您不应使用usingIDisposable.Dispose()来清理客户端,请参阅Avoiding Problems with the Using Statementthis code以获取你开始陷入困惑的世界,关闭这些事情。

答案 2 :(得分:1)

如果您使用的是VS2012,则可以使用*Async这样的呼叫:

var proxy = new MyClient();
var result = await proxy.GetMessagesAsync();

答案 3 :(得分:0)

这样的事情怎么样......

public async Task<string> DoSomething()
{
var someProxy = new ServiceClient();

var t = someProxy.SomeMethodAsync();
await Task.WhenAny(t);

return t.Result;

}