2

我们有一个 WCF 服务,它以下列方式处理传入消息:

public bool ProcessMessage(string message)
{
    var returnValue = GetReturnValue();

    Task.Run(() => {
        //do some things with the message
        UpdateDatabase();
        SendRepliesOverNetwork();
    });

    return returnValue;
}

为了处理尽可能多的消息,我们在此处添加了任务。我们希望尽快将 returnValue 返回给调用者,让 Task 完成它的工作。

我的问题:使用等待的异步数据库调用和/或使用异步方法通过网络进行回复有什么好处吗?

我很谨慎,因为我认为这可能会造成过多的上下文切换。我们已经看到该应用程序在负载下使用了 100 多个线程。

4

2 回答 2

8

首先,我建议你退后一步,认真问问早点回来是不是个好主意。你所做的通常是危险的;在进行实际处理之前,您将“确定”返回给客户端。仅当您的客户知道“returnValue”并不意味着操作已完成并且仅在收到“SendReplies”时才认为它已完成,这才是一个好主意。

就是说,是的,您应该会看到尽可能使一切异步的好处。如果你所有的任务都是非阻塞的,你会更好地利用你的线程池(更少的上下文切换)。

public bool ProcessMessage(string message)
{
  var returnValue = GetReturnValue();

  Task.Run(async () => {
    //do some things with the message
    await UpdateDatabaseAsync();
    await SendRepliesOverNetworkAsync();
  });

  return returnValue;
}
于 2013-04-02T17:51:53.603 回答
4

我可以看到这种方法的几个潜在问题。

首先,如果您在 IIS 中托管 WCF 服务,那么使用比请求寿命更长的后台线程是一个很大的禁忌。当一个请求完成时,IIS 可以自由地拆除整个请求,AppDomain这将中止所有后台工作,并带有极大的偏见!

其次,如果现有工作量增加,WCF 将限制请求。使用这种模式,您可以快速处理请求,线程池排队的工作量可能会无限增加。


您可以尝试使用 WCF 异步服务方法。这将释放正在等待 IO 的线程 - 您的数据库和网络访问 - 这可以提高吞吐量。

这里有一篇关于这种方法的深入文章:Dan Rigsby: Async Operations in WCF

此外,这里的 MSDN 中有一个部分:WCF: Synchronous and Asynchronous Operations

于 2013-04-02T17:52:35.353 回答