真正的异步WCF服务

And*_*sch 8 c# wcf asynchronous

我正在实现一个异步服务.在评估了微软的例子之后,我想知道他们的方法是否真的是异步的.我很确定它是,但我在网上看到的一些样本和AsyncCallback参数让我想知道.

根据示例,我们需要实现BeginEnd方法对,如下所示:

public IAsyncResult BeginGetAcmeAnvil(AsyncCallback callback, object state)
{
  // Starts synchronous task
  var acmeAsyncResult = new AcmeAsyncResult<Anvil>
  {
     Data = new Anvil()
  };      
  return acmeAsyncResult;
}

public Anvil EndGetAcmeAnvil(IAsyncResult result)
{
  var acmeAsyncResult = result as AcmeAsyncResult<Anvil>;

  return acmeAsyncResult != null
    ? acmeAsyncResult.Data
    : new Anvil();
}
Run Code Online (Sandbox Code Playgroud)

非常简单,但为什么我们有AsyncCallback参数?我们不应该调用callback哪个将依次触发End方法?

这就是我的想法:

public delegate void AsyncMethodCaller(AcmeAsyncResult<Anvil> acmeAsyncResult, 
                                       AsyncCallback callback);

public IAsyncResult BeginGetAcmeAnvil(AsyncCallback callback, object state)
{
  var acmeAsyncResult = new AcmeAsyncResult<Anvil>();
  var asyncMethodCaller = new AsyncMethodCaller(GetAnvilAsync);

  // Starts asynchronous task
  asyncMethodCaller.BeginInvoke(acmeAsyncResult, callback, null, null);

  return acmeAsyncResult;
}

private void GetAcmeAnvilAsync(AcmeAsyncResult<Anvil> acmeAsyncResult,
                               AsyncCallback callback)
{
  acmeAsyncResult.Data = new Anvil();
  callback(acmeAsyncResult);  // Triggers EndGetAcmeAnvil
}

public Anvil EndGetAcmeAnvil(IAsyncResult result)
{
  var acmeAsyncResult = result as AcmeAsyncResult<Anvil>;

  return acmeAsyncResult != null
    ? acmeAsyncResult.Data
    : new Anvil();
}
Run Code Online (Sandbox Code Playgroud)

我使用loadUI进行了一些负载测试,但没有明显的性能变化.

And*_*sch 5

我找到了一篇很好的文章,解释了如何从Async WCF服务中获得最佳性能.

要点是:

  1. 不要在Begin方法中做繁重的工作,而且
  2. 做回调以触发End方法.

以下是文字摘录:

为了获得最佳性能,在调用/实现上述异步模式时,有两个原则:

  • 原则1:不要在Begin方法中做重量级的工作......

    这样做的原因是您应该尽快返回调用线程,以便调用者可以安排其他工作.如果它是UI线程,则应用程序需要使用该线程来响应用户输入.如果可能,您应该始终将重要操作放在不同的线程中.

  • 原则2:避免在Begin方法的同一个线程上调用End方法.

    结束方法通常是阻塞.它等待操作完成.如果实现End方法,您会看到它实际上调用了IAsyncResult.WaitHandle.WaitOne().另一方面,作为正常实现,此WaitHandle是一个分配了ManualResetEvent的延迟.只要你不打电话,它根本就不会分配.为了快速操作,这非常便宜.但是,一旦调用End,就必须分配它.调用End的正确位置来自操作的回调.当回调被调用,这意味着阻止工作真正完成.此时,您可以调用End以在不牺牲性能的情况下检索数据.