12

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

4 回答 4

8

如果您选择“生成异步操作”,您将获得必须使用回调的“旧”行为。

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

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

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

如您所见,没有更多的回调。而是Task<T>返回 a。

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

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

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

于 2012-12-08T14:14:34.137 回答
3

您的服务参考(如果您使用的是 .Net 4.5)可以设置为生成基于任务的异步调用。(配置服务参考>检查允许生成异步操作>选择生成基于任务的操作)这些可以像任何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,则无法生成使用 .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()清理客户端,请参阅使用 Using 语句避免问题此代码,让您开始进入关闭这些东西的混乱世界。

于 2012-12-08T13:55:39.917 回答
1

如果您使用的是 VS2012,那么您可以使用如下*Async调用:

var proxy = new MyClient();
var result = await proxy.GetMessagesAsync();
于 2012-12-08T14:07:21.607 回答
0

像这样的东西怎么样...

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

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

return t.Result;

}

于 2012-12-08T13:45:13.083 回答