I'd been using Jeff Wilcox's handy Silverlight Unit Test Framework to test the data access piece of my current Silverlight project. However, I was running into a nasty problem that was driving me nuts. Part way through every test run, my unit tests would start failing. I could usually get through something like 10 or so tests before every new WCF call would return "Not Found" (which is not really the most helpful error message Microsoft ever came up with). It didn't have anything to do with the individual tests themselves, because the error would show up after 10 tests, no matter which 10 tests they were. I'd been working through this error for some time before I realized that the "10" number was undoubtedly significant, since that seems to be the default number of connections that WCF allows, unless you go in and bump it higher. (Now of course, IMO, that's a pretty dumb default: the obvious purpose for leaving it that low is to prevent DOS attacks -- but the net result is that instead of needing some 10,000 connections to DOS your server, you only need 10. Sigh.)
This made me think that I might be leaking a connection somewhere. In theory, I was closing all my connections in one test before moving on to another, but we all know how well that works :-). Since I was opening and closing all my connections through the same static class, I wrote up some quick instrumentation, and saw that yeah, one connection was staying open after every test. Some additional poking around, and I found a method that was opening a new connection and failing to close it. Easily fixed. Instead of this final line in my method:
EnqueueTestComplete();
I just made it do this:
EnqueueCallback(() => DataConnectionManager.TryClientClose(client,
error => EnqueueTestComplete()));
And TryClientClose() looks something like this:
public static void TryClientClose(RoomServiceClient client, OperationCallback callback)
{
if (client != null && client.State == CommunicationState.Opened)
{
client.CloseCompleted += (sender, e) =>
{
ClientsClosed++;
ClientsOpen--;
if (e.Error != null)
{
client.Abort();
}
if (callback != null)
{
callback(e.Error);
}
};
client.CloseAsync();
}
else
{
if (callback != null)
{
callback(null);
}
}
}
Close enough. But why was I running into this error in the first place? Truth be told, I don't completely know. But my best guess is that the Silverlight client (or maybe the browser that's hosting it) has a limitation on how many duplex callback sessions it can support. And so far as I'm aware, there's no way to increase this number. At least, I've poked around in all the relevant blogs, and looked through the appropriate docs, and can't find anything obvious. But the net result is that you don't want to have more than 10 duplex clients open at the same time on any given Silverlight application.