2007-03-13 Adar Wesley <adarw@mainsoft.com>
authorAdar Wesley <adar@mono-cvs.ximian.com>
Tue, 13 Mar 2007 09:58:40 +0000 (09:58 -0000)
committerAdar Wesley <adar@mono-cvs.ximian.com>
Tue, 13 Mar 2007 09:58:40 +0000 (09:58 -0000)
        * Page.cs: improved Async Page implementation.

svn path=/trunk/mcs/; revision=74160

mcs/class/System.Web/System.Web.UI/ChangeLog
mcs/class/System.Web/System.Web.UI/Page.cs
mcs/class/System.Web/Test/System.Web.UI/PageTest.cs

index fcb9290d64a13ca3593c85175ef19c27bd51072a..b65f4032e6306cbcac7c780b74afd86ab43cd54e 100644 (file)
@@ -1,3 +1,7 @@
+2007-03-13  Adar Wesley <adarw@mainsoft.com>
+
+       * Page.cs: improved Async Page implementation.
+
 2007-03-13  Marek Habersack  <mhabersack@novell.com>
 
        * TemplateControl.cs: implement AppRelativeVirtualPath. Closes bug
index d9cbd2b1051a97419abbfedb050737005d6c674b..3eddc646f06dbe25408d55fe61b0308884e335ec 100644 (file)
@@ -2114,20 +2114,29 @@ public partial class Page : TemplateControl, IHttpHandler
                        DateTime startExecution = DateTime.Now;
                        List<PageAsyncTask> localParallelTasks = parallelTasks;
                        parallelTasks = null; // Shouldn't execute tasks twice
-                       WaitHandle [] waitArray = new WaitHandle [localParallelTasks.Count];
-                       IAsyncResult [] asyncResults = new IAsyncResult [localParallelTasks.Count];
-                       int i = 0;
+                       List<IAsyncResult> asyncResults = new List<IAsyncResult>();
                        foreach (PageAsyncTask parallelTask in localParallelTasks) {
-                               asyncResults[i] = parallelTask.BeginHandler (this, null, new AsyncCallback(EndAsyncTaskCallback), parallelTask.State);
-                               waitArray [i] = asyncResults[i].AsyncWaitHandle;
-                               i++;
+                               IAsyncResult result = parallelTask.BeginHandler (this, EventArgs.Empty, new AsyncCallback (EndAsyncTaskCallback), parallelTask.State);
+                               if (result.CompletedSynchronously) {
+                                       parallelTask.EndHandler (result);
+                               }
+                               else {
+                                       asyncResults.Add (result);
+                               }
                        }
 
-                       bool allSignalled = WaitHandle.WaitAll (waitArray, AsyncTimeout, false);
-                       if (!allSignalled) {
-                               for (i = 0; i < asyncResults.Length; i++) {
-                                       if (!asyncResults [i].IsCompleted) {
-                                               localParallelTasks [i].TimeoutHandler (asyncResults [i]);
+                       if (asyncResults.Count > 0) {
+                               WaitHandle [] waitArray = new WaitHandle [asyncResults.Count];
+                               int i = 0;
+                               for (i = 0; i < asyncResults.Count; i++) {
+                                       waitArray [i] = asyncResults [i].AsyncWaitHandle;
+                               }
+                               bool allSignalled = WaitHandle.WaitAll (waitArray, AsyncTimeout, false);
+                               if (!allSignalled) {
+                                       for (i = 0; i < asyncResults.Count; i++) {
+                                               if (!asyncResults [i].IsCompleted) {
+                                                       localParallelTasks [i].TimeoutHandler (asyncResults [i]);
+                                               }
                                        }
                                }
                        }
@@ -2142,15 +2151,21 @@ public partial class Page : TemplateControl, IHttpHandler
                }
 
                if (serialTasks != null) {
-                       foreach (PageAsyncTask serialTask in serialTasks) {
+                       List<PageAsyncTask> localSerialTasks = serialTasks;
+                       serialTasks = null; // Shouldn't execute tasks twice
+                       foreach (PageAsyncTask serialTask in localSerialTasks) {
                                DateTime startExecution = DateTime.Now;
 
-                               IAsyncResult result = serialTask.BeginHandler (this, null, new AsyncCallback (EndAsyncTaskCallback), serialTask);
-                               bool done = result.AsyncWaitHandle.WaitOne (AsyncTimeout, false);
-                               if (!done && !result.IsCompleted) {
-                                       serialTask.TimeoutHandler (result);
+                               IAsyncResult result = serialTask.BeginHandler (this, EventArgs.Empty, new AsyncCallback (EndAsyncTaskCallback), serialTask);
+                               if (result.CompletedSynchronously) {
+                                       serialTask.EndHandler (result);
+                               }
+                               else {
+                                       bool done = result.AsyncWaitHandle.WaitOne (AsyncTimeout, false);
+                                       if (!done && !result.IsCompleted) {
+                                               serialTask.TimeoutHandler (result);
+                                       }
                                }
-
                                DateTime endWait = DateTime.Now;
                                TimeSpan elapsed = endWait - startExecution;
                                if (elapsed <= AsyncTimeout) {
index 38d2c9e4d0151fc4ef9fc4803193087d13927d6a..1bf2e86254c131580528c9b951683d4f3a2d723d 100644 (file)
@@ -695,8 +695,6 @@ namespace MonoTests.System.Web.UI {
                        Assert.AreEqual ("EndGetAsyncData", eventlist[1], "EndGetAsyncData Failed");
                }
 
-
-               
                [Test]
 #if !TARGET_JVM
                [Category ("NotWorking")] // Mono PageParser does not handle @Page Async=true
@@ -715,6 +713,32 @@ namespace MonoTests.System.Web.UI {
                        Assert.AreEqual ("EndGetAsyncData", eventlist[1], "EndGetAsyncData Failed");
                }
 
+               [Test]
+               [Category ("NunitWeb")]
+#if !TARGET_JVM
+               [Category ("NotWorking")] // Mono PageParser does not handle @Page Async=true
+#endif
+               [ExpectedException (typeof (Exception))]
+               public void AddOnPreRenderCompleteAsyncBeginThrows () 
+               {
+                       WebTest t = new WebTest ("AsyncPage.aspx");
+                       t.Invoker = PageInvoker.CreateOnLoad (AddOnPreRenderCompleteAsyncBeginThrows_Load);
+                       string str = t.Run ();
+               }
+
+               [Test]
+               [Category ("NunitWeb")]
+#if !TARGET_JVM
+               [Category ("NotWorking")] // Mono PageParser does not handle @Page Async=true
+#endif
+               [ExpectedException (typeof (Exception))]
+               public void AddOnPreRenderCompleteAsyncEndThrows () 
+               {
+                       WebTest t = new WebTest ("AsyncPage.aspx");
+                       t.Invoker = PageInvoker.CreateOnLoad (AddOnPreRenderCompleteAsyncEndThrows_Load);
+                       string str = t.Run ();
+               }
+
                public static void ExecuteRegisteredAsyncTasks_Load (Page p)
                {
                        BeginEventHandler bh = new BeginEventHandler (BeginGetAsyncData);
@@ -735,7 +759,29 @@ namespace MonoTests.System.Web.UI {
                        myRequest = WebRequest.Create(address);
                }
 
-               static IAsyncResult BeginGetAsyncData(Object src, EventArgs args, AsyncCallback cb, Object state)
+               public static void AddOnPreRenderCompleteAsyncBeginThrows_Load (Page p) 
+               {
+                       BeginEventHandler bh = new BeginEventHandler (BeginGetAsyncDataThrows);
+                       EndEventHandler eh = new EndEventHandler (EndGetAsyncData);
+                       p.AddOnPreRenderCompleteAsync (bh, eh);
+
+                       // Initialize the WebRequest.
+                       string address = "http://MyPage.aspx";
+                       myRequest = WebRequest.Create (address);
+               }
+
+               public static void AddOnPreRenderCompleteAsyncEndThrows_Load (Page p) 
+               {
+                       BeginEventHandler bh = new BeginEventHandler (BeginGetAsyncData);
+                       EndEventHandler eh = new EndEventHandler (EndGetAsyncDataThrows);
+                       p.AddOnPreRenderCompleteAsync (bh, eh);
+
+                       // Initialize the WebRequest.
+                       string address = "http://MyPage.aspx";
+                       myRequest = WebRequest.Create (address);
+               }
+
+               static IAsyncResult BeginGetAsyncData (Object src, EventArgs args, AsyncCallback cb, Object state)
                {
                        if (WebTest.CurrentTest.UserData == null) {
                                ArrayList list = new ArrayList ();
@@ -752,7 +798,24 @@ namespace MonoTests.System.Web.UI {
                        return new Customresult(); // myRequest.BeginGetResponse (cb, state);
                }
 
-               static void EndGetAsyncData(IAsyncResult ar)
+               static IAsyncResult BeginGetAsyncDataThrows (Object src, EventArgs args, AsyncCallback cb, Object state) 
+               {
+                       ArrayList list = null;
+                       if (WebTest.CurrentTest.UserData == null) {
+                               list = new ArrayList ();
+                       }
+                       else {
+                               list = WebTest.CurrentTest.UserData as ArrayList;
+                               if (list == null)
+                                       throw new NullReferenceException ();
+                       }
+                       list.Add ("BeginGetAsyncData");
+                       WebTest.CurrentTest.UserData = list;
+
+                       throw new Exception ("BeginGetAsyncDataThrows");
+               }
+
+               static void EndGetAsyncData (IAsyncResult ar)
                {
                        if (WebTest.CurrentTest.UserData == null) {
                                ArrayList list = new ArrayList ();
@@ -768,6 +831,23 @@ namespace MonoTests.System.Web.UI {
                        }
                }
 
+               static void EndGetAsyncDataThrows (IAsyncResult ar) 
+               {
+                       ArrayList list = null;
+                       if (WebTest.CurrentTest.UserData == null) {
+                               list = new ArrayList ();
+                       }
+                       else {
+                               list = WebTest.CurrentTest.UserData as ArrayList;
+                               if (list == null)
+                                       throw new NullReferenceException ();
+                       }
+                       list.Add ("EndGetAsyncData");
+                       WebTest.CurrentTest.UserData = list;
+
+                       throw new Exception ("EndGetAsyncDataThrows");
+               }
+
                [Test]
                public void AsyncMode ()
                {