0

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

好的,所以标题可能没有给出最好的描述。让我先描述一下我要做什么。我们有一个 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。当数据库连接可用时,它将分配(例如)Responses[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
}

我们还研究了具有队列或使用诸如 Pulse/Monitor.Wait(我们不熟悉)之类的 DbManager。

所以,问题是:我们怎样才能有一个异步 WCF 操作在它能够返回时返回?

4

3 回答 3

2

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

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

于 2013-05-24T23:40:33.700 回答
1

如果您只有一个数据库服务器(我怀疑这很可能),那么只需将 aBlockingCollection用于您的池。

于 2013-05-25T02:16:25.717 回答
1

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

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

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

于 2013-05-24T23:37:43.527 回答