I have an program where I need to create some large number of folders to an external sharepoint site (external meaning I can’t use the sharepoint object model). Web requests work well for this, but simply doing them one at a time (send request, wait for response, repeat) is rather slow. I decided to multithread the requests, to try and speed it up. The program has sped up considerably, but after some amount of time (between 1-2 minutes or so), concurrency exceptions start getting thrown.
Code is below, is this the best way to go about this?
Semaphore Lock = new Semaphore(10, 10);
List<string> folderPathList = new List<string>();
//folderPathList populated
foreach (string folderPath in folderPathList)
{
Lock.WaitOne();
new Thread(delegate()
{
WebRequest request = WebRequest.Create(folderPath);
request.Credentials = DefaultCredentials;
request.Method = "MKCOL";
WebResponse response = request.GetResponse();
response.Close();
Lock.Release();
}).Start();
}
for(int i = 1;i <= 10;i++)
{
Lock.WaitOne();
}
The exception is something along the lines of
Unhandled Exception: System.Net.WebException: Unable to connect to the remote server —> System.Net.Sockets.SocketException: Only one useage of each socket address is normally permitted 192.0.0.1:81
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddre
ss socketAddress)
at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state,
IAsyncResult asyncResult, Int32 timeout, Exception& exception)
You might create too many connections, thus using up all the local ports you can use.
There’s a timeout period for when a port can be reused after you close it.
WebRequesthides all the low level socket handling for you, but I am guessing it eventually runs out of ports, or tries to (re)bind to a socket already in a TIME_WAIT state.You should make sure you read the response stream, even if you don’t care about the response. This should help not producing too many lingering connections.
I’ll paste some relevant info from here:
OK now how can this be fixed?
One of the ways is to increase the dynamic port range. The max by default is 5000. You can set this up to 65534.
HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\MaxUserPortis the key to use.The second thing you can do is once the connection does get into an TIME_WAIT state you can reduce the time it is
in that state, Default is 4 minutes, but you can set this to 30 seconds
HKLM\System\CurrentControlSet\Services\Tcpip\Parameters\TCPTimedWaitDelayis the key to use.Set this to 30 seconds