Net 4.5 Task-based Asynchronous Pattern (TAP) using web forms and user controls There seems to some tricky differences between webforms, winforms, WCF and MVC approaches. So far I have: In my <%@ Page Async="true"
In Web Config: appSettings - add key="aspnet:UseTaskFriendlySynchronizationContext" (This means I can use Tasks without having to register them in my page?)
My User control will call a web service to get a User profile based on a Membership Number. In my User Control I want to display a progress bar while the long running process proceeds. Since the actual length of the call will always be undetermined the timing of the progress bar will be a little faked (Currently 10 seconds to complete the task). I tried to use the Task IProgress reporting but I found it would only report the start and the end of the process in webforms, not intermediate steps, so I created a Javascript reporter for the UI and call ajax to a fake status processor. My Ajax responds with a % complete in a custom Response.AppendHeader(ProgressStatus, value);
So System.Web.HttpResponse HttpContext.Current is key to this but when I run my Task, HttpContext.Current gets blocked and the prog bar starts after the Task is complete. I Can't see where the Thread gets blocked?
Here is some code: UserControl.ascx.cs
protected void Page_Load(object sender, EventArgs e)
{
Response.AddHeader("cache-control", "no-cache");
if (!Page.IsPostBack)
{
InitialiseControl();
}
}
public async void InitialiseControl() // Its an event
{
// wait for a command from the ajax
if (Request["startTask"] != null)
{
//..do some progress stuff
await GetUserProfileAsync(request.MembershipNumber);
//..Report back to the UI
}
if (Request["getStatus"] != null)
{
//..polling from the ajax, continue with progress reporting back to the UI
}
}
// we are still in HttpContext.Current so add object to session
private async Task GetUserProfileAsync(string membershipNumber)
{
UserProfile profile =
await WebApplication.Library.Methods.Membership.UserProfile.GetUsersProfileTaskAsync(membershipNumber);
HttpContext.Current.Session["UserProfile_" + membershipNumber] = profile;
}
WebApplication.Library.Methods.Membership.UserProfile:
public async static Task<UserProfile> GetUsersProfileTaskAsync(string usersMembershipNumber)
{
Task<UserProfile> t = new Task<UserProfile>
(
() =>
{
UserProfile profile = new UserProfile() { Name = "Some name",
Password = "TestPassword",
MembershipNumber = usersMembershipNumber };
return profile;
}
);
// start the task
t.Start();
int i = 0;
for (i = 0; i < 8; i++)
{
// Fake delay simulating a web service
Thread.Sleep(1000);
}
if (i == 8)
{
return await t;
}
return null;
}
Hi Stephen thanks for your reply. "I hope by this that you mean it sends a complete response" My JavaScript picks up the response as a full header returned: xmlhttp.getResponseHeader("ProgressStatus");
However Im not even sure my code is running asyncly. If I try to register my Task on Page Load:
this.Page.RegisterAsyncTask(new PageAsyncTask(() => GetUserProfileAsync(membershipNumber))); (does this approach refer to the legacy usage for Async? and not the 4.5 Task usage)
I get Error: Task-returning Page methods are unsupported in the current application configuration. To work around this, remove the following configuration switch in Web.config: add key="aspnet:UseTaskFriendlySynchronizationContext"
When I remove the switch: System.InvalidOperationException: An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.
This error occurs at InitialiseControl();
I think the first thing is to prove we can do async in a UserControl. This is the first time I have used any Async stuff and I have spent a lot of time watching the fantastic videos made by Lucian Wischik, but he never really covers webforms (which I have to use since my company will not move to MVC).