|
dev
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
WebResponse.Close() not disposing unmanaged resource?and it appears to be leaking memory. I've spent a couple of days working with the excellent .net memory profiler from Scitech (http://www.scitech.se/) trying to find the leak, and all I've managed to find is that the win32 (unmanaged) heap seems to keep growing. I wrote this (pretty non-realistic) code in a test app to try duplicating the problem: while(true) { try { System.Net.WebRequest req=System.Net.WebRequest.Create(@"http://chris/TestWebService/TestService.asmx?WSDL"); System.Net.WebResponse resp=req.GetResponse(); resp.Close(); } catch(Exception ex) { MessageBox.Show(ex.ToString()); } } Note that this was just inside a button click event of a winform application. The exception condition never got hit, and the app just kept hammering away at my local web server. Checking the profiler, I saw the number of undisposed instances of System.Net.HttpWebResponse, System.Net.ConnectStream, and System.Threading.ManualResetEvent increasing with each iteration. Shouldn't the resp.Close() statement release the resources? There's nothing in the documentation about doing any sort of disposal on the request object, so it appears that only the response needs to be disposed, and so far, that doesn't seem to be happening. I've also tried the above code casting the response to an HTTPWebResponse, but that has no effect. I also tried removing the resp.Close() statement, which had no effect (the undisposed objects still showed up in the profiler). Is there something else I need to do to fix this memory leak? Thanks for your help, Chris Hi Chris,
don't know if makes any change, but the WebResponse class implements the IDisposable interface, so you could try a using statement: using (System.Net.WebResponse resp=req.GetResponse()) { // do some stuff with resp if you want. } If there's any cleanup code in the WebRespone.Dispose implementation, it will be executed as soon as the using block is left and it will be executed even if an exception is thrown. Michael <cmbar***@engmail.uwaterloo.ca> schrieb im Newsbeitrag Show quote news:1131564602.694642.104070@g14g2000cwa.googlegroups.com... >I have a .net app that uses a lot of calls to System.Net.WebRequest, > and it appears to be leaking memory. I've spent a couple of days > working with the excellent .net memory profiler from Scitech > (http://www.scitech.se/) trying to find the leak, and all I've managed > to find is that the win32 (unmanaged) heap seems to keep growing. I > wrote this (pretty non-realistic) code in a test app to try duplicating > the problem: > > while(true) > { > try > { > System.Net.WebRequest > req=System.Net.WebRequest.Create(@"http://chris/TestWebService/TestService.asmx?WSDL"); > System.Net.WebResponse resp=req.GetResponse(); > resp.Close(); > } > catch(Exception ex) > { > MessageBox.Show(ex.ToString()); > } > } > > > Note that this was just inside a button click event of a winform > application. The exception condition never got hit, and the app just > kept hammering away at my local web server. Checking the profiler, I > saw the number of undisposed instances of System.Net.HttpWebResponse, > System.Net.ConnectStream, and System.Threading.ManualResetEvent > increasing with each iteration. Shouldn't the resp.Close() statement > release the resources? There's nothing in the documentation about > doing any sort of disposal on the request object, so it appears that > only the response needs to be disposed, and so far, that doesn't seem > to be happening. I've also tried the above code casting the response to > an HTTPWebResponse, but that has no effect. I also tried removing the > resp.Close() statement, which had no effect (the undisposed objects > still showed up in the profiler). Is there something else I need to do > to fix this memory leak? > > Thanks for your help, > > Chris > Thanks for the reply Michael. I tried your suggestion just after I
posted actually, and I found that putting the using statement in got rid of the undisposed webResponse objects, but left the System.Net.ConnectStream and System.Threading.ManualResetEvent objects undisposed. I know that the ManualResetEvent is created by HTTPWebRequest.GetResponse, and the ConnectStream is called by HttpWebRequest.BeginSubmitRequest. The first problem is that these last two undisposed instances are created by the request, which does not implement IDisposable, and does not have anything in the documentation regarding unmanaged resources. Is there something that I need to do to clean up after a WebRequest? Second, why does the using statement work for the response, but not the close() method? The documentation explicitly states : "The Close method closes the response stream and releases the connection to the Internet resource for reuse by other requests. Note You must call either the Stream.Close or the HttpWebResponse.Close method to close the stream and release the connection for reuse. It is not necessary to call both Stream.Close and HttpWebResponse.Close, but doing so does not cause an error. Failure to close the stream will cause your application to run out of connections." Does this mean that Close() doesn't actually call Dispose()? I'm a little confused-I thought that this was the reason that the close method existed on stream objects. The code that I'm using is almost identical to the MSDN sample code. Seems to be a bug in the .NET Framework 1.1. I found some interesting
information about it at http://dturini.blogspot.com/2004/06/on-past-few-days-im-dealing-with-some.html Michael <cmbar***@engmail.uwaterloo.ca> schrieb im Newsbeitrag Show quote news:1131569401.178280.239950@g44g2000cwa.googlegroups.com... > Thanks for the reply Michael. I tried your suggestion just after I > posted actually, and I found that putting the using statement in got > rid of the undisposed webResponse objects, but left the > System.Net.ConnectStream and System.Threading.ManualResetEvent objects > undisposed. I know that the ManualResetEvent is created by > HTTPWebRequest.GetResponse, and the ConnectStream is called by > HttpWebRequest.BeginSubmitRequest. > > The first problem is that these last two undisposed instances are > created by the request, which does not implement IDisposable, and does > not have anything in the documentation regarding unmanaged resources. > Is there something that I need to do to clean up after a WebRequest? > > Second, why does the using statement work for the response, but not the > close() method? The documentation explicitly states : > > "The Close method closes the response stream and releases the > connection to the Internet resource for reuse by other requests. Note > You must call either the Stream.Close or the HttpWebResponse.Close > method to close the stream and release the connection for reuse. It is > not necessary to call both Stream.Close and HttpWebResponse.Close, but > doing so does not cause an error. Failure to close the stream will > cause your application to run out of connections." > > Does this mean that Close() doesn't actually call Dispose()? I'm a > little confused-I thought that this was the reason that the close > method existed on stream objects. The code that I'm using is almost > identical to the MSDN sample code. > I had this exact same issue. I worked with MS and they gave me a hotfix that
fixed the problem. There is a KB article that you can use to get the hotfix, however, the KB doesn't describe the problem. The rep I worked with said this hotfix fixes a few other undocumented issues. This is one of them. http://support.microsoft.com/?kbid=907432 I ran a load on the server overnight and it worked great. |
|||||||||||||||||||||||