On Sun, 30 Nov 2003 05:09:09 GMT, "Justice" <ju**********@hotmail.com>
wrote:
"Steve van Dongen" <st*****@hotmail.com> wrote in message
news:uk********************************@4ax.com.. . Been there, done that.
> AsyncQueue[index].Server.abort();
>
> AsyncQueue[index].Server = null;
>
> delete AsyncQueue[index].Server;
>
> AsyncQueue[index].ThisElement = null;
>
> delete AsyncQueue[index].ThisElement;
>
> AsyncQueue[index] = null;
You don't need to call abort() or any of the 4 lines after that.
It looks like you may actually need to set .Server and .ThisElement =
null though frankly I'm not sure why.
> CollectGarbage();
CollectGarbage won't solve your problems. It is only useful in
debugging as it forces the garbage collector to run at a known point.
I simply threw it in to see if memory was actually being deallocated.
Unfortunately, nothing really changed.
Aside from executing code too many times (the f() function is called 3
times per HTTP request and you loop through each item in your array),
How can I necessarily avoid calling f three times, however? Attaching f to
onreadystatechange basically guarantees that this thing is going to get
called every time.
Ideally, I would have liked a way in "f" to determine which server object
fired the onreadystatechange event, but no information comes back from
onreadystatechange to indicate this, hence my convoluted attempts at
resolving things.
See below.
there doesn't appear to be any problems noticable at first glance.
But this isn't your actual code, is it? It doesn't make much sense to
make HTTP requests but do nothing with the results....
You're correct. However, even this code (without anything notable in
function "f", which would do something w/ the results) leads to memory
leaks. If I simulate an environment where, say, 400 of these requests are
made, the memory piles up and piles up and eventually I have IE using 156
megabytes of memory.
Unfortunately, although there don't *seem* to be any problems noticeable
(that's what I thought too, other than some semi-inefficient ways of going
through the asynclist) the memory allocations for this are enormous when 200
or so requests go through.
Whenever you use nested functions, a closure is created, giving the
enclosed function access to all of the outer function's arguments and
local variables. This is a common source of memory leaks. The
problem comes down to how relatively easy it is to create circular
references when you don't realize what is really going on. The
JScript garbage collector is capable of breaking circular references
between any number of JScript objects, but it cannot break a circular
reference where the chain includes an external object like an element
in IE or a COM object.
So, the point is basically, try not to mix nested functions and DHTML
and/or ActiveX because you might end up with a circular reference that
cannot be broken and, therefore, a memory leak.
This is an example of a function that leaks memory...
function omicron()
{
var x = MakeNewDiv();
x.foo = epsilon;
function epsilon()
{
...
}
}
The circular reference is:
x --> div --> epsilon --> x
That said, the only way to pass data to your onreadystatechange
handler is to use a closure. This example doesn't leak...
AsyncQueue = new Array();
asyncsRunning = 0;
function Init()
{
for (var i=0; i<500; i++)
{
AsyncRequestStart("", "id" + i);
}
}
function AsyncRequestStart(value, id)
{
var index;
var requestInfo = new Object();
index = AsyncQueue.length;
AsyncQueue.push(requestInfo);
// requestInfo.ThisElement = document.getElementById(id);
requestInfo.Server = new ActiveXObject("Msxml2.XMLHTTP");
requestInfo.Server.onreadystatechange = function () {
AsyncRequestComplete(index);
};
requestInfo.Server.open("GET",
"http://localhost/MyCompany/data.metadata?text=" + value, true);
requestInfo.Server.send(value);
asyncsRunning++;
}
function AsyncRequestComplete(index)
{
var requestInfo = AsyncQueue[index];
Log(index + ": readyState=" + requestInfo.Server.readyState);
if (requestInfo.Server.readyState == 4 /*FINISHED*/)
{
asyncsRunning--;
UpdateStatus();
// requestInfo.ThisElement = null;
requestInfo.Server = null;
delete AsyncQueue[index];
}
requestInfo = null;
}
function Log(s)
{
window.status = s;
}
function UpdateStatus()
{
document.body.innerText = "Pending Requests: "
+ asyncsRunning;
}
Regards,
Steve
--
Please post questions to the newsgroup; everyone benefits.
This post is provided "AS IS" with no warranties, and confers no rights
Sample code subject to
http://www.microsoft.com/info/cpyright.htm