为了使这更容易理解:我们正在使用一个没有内置连接池的数据库。我们正在实现自己的连接池。
好的,所以标题可能没有给出最好的描述。首先让我描述一下我要做的事情。我们有一个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操作?
答案 0 :(得分: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
来设置结果。
答案 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
。