异步WCF服务

时间:2013-05-24 23:27:23

标签: c# wcf asynchronous

为了使这更容易理解:我们正在使用一个没有内置连接池的数据库。我们正在实现自己的连接池。

好的,所以标题可能没有给出最好的描述。首先让我描述一下我要做的事情。我们有一个WCF服务(托管在Windows服务中),需要能够一次处理/处理多个请求。 WCF服务将接受请求并尝试与(例如)10个可用的数据库连接进行通信。这些数据库连接都由WCF服务跟踪,并且处理设置为忙时。如果请求进入并且WCF尝试与10个数据库连接之一进行通信并且所有这些连接都设置为忙,我们希望WCF服务等待并在响应可用时返回响应。

我们尝试了一些不同的东西。例如,我们可以使用while循环(yuck)

[OperationContract(AsyncPattern=true)]
ExecuteProgram(string clientId, string program, string[] args)
{
    string requestId = DbManager.RegisterRequest(clientId, program, args);
    string response = null;
    while(response == null)
    {
        response = DbManager.GetResponseForRequestId(requestId);
    }

    return response;
}

基本上DbManager会跟踪请求和响应。每个请求都会调用DbManager,它将分配一个请求ID。当数据库连接可用时,它将分配(例如)响应[requestId] = [数据库响应]。该请求将不断询问DbManager是否有响应,何时请求可以返回它。

这到处都有问题。我们可能有多个线程卡在while循环中,谁知道多长时间。这对性能和CPU使用率来说太糟糕了。 (至少可以说)

我们也考虑过使用事件/听众来尝试这个。我不知道如何实现这一点,所以下面的代码更多的是我们设想它的运作方式。

[OperationContract(AsyncPattern=true)]
ExecuteProgram(string clientId, string program, string[] args)
{
    // register an event
    // listen for that event
    // when that event is called return its value
}

我们还研究了DbManager有队列或使用像Pulse / Monitor.Wait这样的东西(我们不熟悉)。

所以,问题是:我们怎样才能有能够返回的异步WCF操作?

3 个答案:

答案 0 :(得分:2)

WCF支持.net 4.5 http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx中的async / await关键字。您需要进行一些重构才能使ExecuteProgram异步并使您的DbManager请求操作等待。

如果您需要DbManager来管理这些任务的完成,因为结果可用于给定的clientId,您可以将每个clientId映射到TaskCompletionSourceTaskCompletionSource可用于创建Task,DbManager可以使用TaskCompletionSource来设置结果。

答案 1 :(得分:1)

这应该可以使用正确实现的async方法来调用:

[OperationContract]
string ExecuteProgram(string clientId, string program, string[] args)
{
    Task<string> task = DbManager.DoRequestAsync(clientId, program, args);
    return task.Result;
}

您是否手动管理10个数据库连接?听起来你已经重新实现了数据库连接池。也许您应该使用内置于数据库服务器或驱动程序的连接池。

答案 2 :(得分:1)

如果您只有一个数据库服务器(我怀疑可能是这样),那么只需为您的池使用BlockingCollection