【问题标题】:Truly asynchronous WCF service真正的异步 WCF 服务
【发布时间】:2011-11-09 12:27:26
【问题描述】:

我正在实现一个异步服务。在评估了微软的example 之后,我想知道他们的方法是否真的是异步的。我很确定是这样,但是我在网上看到的一些示例和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();
}

很简单,但为什么我们有一个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();
}

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

【问题讨论】:

    标签: c# wcf asynchronous


    【解决方案1】:

    我找到了good article,它解释了如何从 Async WCF 服务中获得最佳性能。

    要点是:

    1. 不要在 Begin 方法中做繁重的工作,并且
    2. 请务必进行回调以触发 End 方法。

    这是一段文字的摘录:

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

    • 原则 1: 不要在 Begin 方法内做繁重的工作...

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

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

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

    【讨论】:

      【解决方案2】:

      我认为它像这样分开的主要原因是 WCF 运行时正在处理线程同步,而不是您必须手动处理它。

      如果您通过回调调用 end 方法,则必须处理同步,这会使模式变得相当复杂(如您在编码示例中所见)。这种模式的目标不是让您真正了解线程的东西,您只想编写长时间运行的操作,而不必考虑线程的实现细节。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-03
        • 2011-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多