I have googled around for hours now. I haven't found any satisfactory solution to the following problem.
Consider the following .aspx
<asp:ScriptManager runat="server" /><asp:UpdatePanel runat="server" ID="UpdatePanel1"><ContentTemplate><asp:Timer runat="server" ID="Timer1" OnTick="Timer1_Tick" Interval="5000" /><asp:Label runat="server" ID="Label1"></asp:Label></ContentTemplate></asp:UpdatePanel>
with the following .cs
protected void Timer1_Tick(object sender, EventArgs e)
{
if (ViewState["Count"] == null)
{
ViewState["Count"] = (int)0;
}
int count = (int)ViewState["Count"];
Label1.Text = (count++).ToString();
ViewState["Count"] = count;
}This construction is a memory-hog browser side. (I tested with IE9 only. Considering what I found, I am guessing the other browsers have the same problem. This is not a typical memory leak or pseudo memory leak in IE that I have seen others complain about. Also, I can't go tell my users not to use IE anyway.)
Using sIEve I have found that on each Tick of the Timer, the DOM gets one more script added that creates the Timer. It's not big, but over time it builds up. (The Timer does Tick only once, though. So apparently, all those extra lines don't really do anything. They just keep memory allocated.)
The "DOM Nodes in use" of sIEve show the following line over and over. And when I refresh it seems it is only more of this line that gets added.
<SCRIPT type=text/javascript __sIEve_hookedNode="true">Sys.Application.add_init(function() { $create(Sys.UI._Timer, {"enabled":true, "interval":...Apart from this line mentioning Timer, I see this happening only in pages with a Timer. (A simple page with a Button for PostBack doesn't seem to produce any extra lines.)
I am amazed that a page as simple as this can cause a problem, and noone else has found it a problem.
On the actual page in our application, users can keep the page open for a long time to watch the status of the system for which the application is the front end. Some even do so over the weekend. (We tell them not to, but they do it anyway.) We have seen IE use up over 1.5GB due to this. And IE (or Windows) doesn't like it when that happens.
I did found two "solutions":
- Put the Timer outside the UpdatePanel and use an ASyncPostBackTrigger to make it refresh only the UpdatePanel. This works...for the demo. But in the actual pages, the UpdatePanel is in a MasterPage. The Timer is in a UserControl that is in a Page using the MasterPage. So this is not helping us. Also, some Pages with a Timer have Nested UpdatePanels to further complicate the matter.
- Reload the page. This can ge done by doing a Response.Redirect in the Tick handler of the Timer. Again, this works...for the demo. In the actual page, the Timer refreshes a part of the Page, while the user may be editing data in another part. A full page refresh will make the user lose the data entered. Also, I have no idea how to get the focus back where it was after the reload. (Or rather, I have no idea how to find out where it was before the PostBack.) We don't want to annoy our users with this. Although, if there really, really, really is no other option, I guess we could do a reload every hour or so. Users will be annoyed, but only every now and then.
Has anyone had similar problems? If so, how did you get around it?
While doing the research on this, I also found that some of our pages have a hidden input named _VIEWSTATEENCRYPTED that behaves pretty much like the add_init script of the Timer. If anyone has any idea what that is about, I am also quite interested. (Specifically: why does it keep a reference. I already know what the input itself means.)