6

I have this API client which has a send method used to post my object to a Web API service and return an object of type ReturnedResults. Now I need to run this post method in an ASP.net page_load event. I have seen similar examples here, however what I need is to get my return object from my async method.

I know that I am supposed to use

PageAsyncTask t = new PageAsyncTask(APIService.Send("test"));

However I have two problems, first PageAsyncTask doesn't accept my Send method as a valid Task type, I guess that's because my method returns a Task of Task type so it complains that it can't convert Task to System.Func

Also how can I get my object of ReturnedResults out of this once it is successfully executed?

user65248
  • 471
  • 1
  • 5
  • 17
  • 3
    https://stackoverflow.com/questions/35899800/can-page-load-be-async – Mike Nov 17 '17 at 02:19
  • Thanks but I have seen those articles, none of them are helpful for my case, I need to get the result out of my async method, and at the same time let it pause the page load until the wait for the async method is over. – user65248 Nov 17 '17 at 09:09
  • Ideally, not a good idea to put heavy load method in Page_Load. I'm not sure how your requirement is. However, it might need to revise your system design probably. – Mike Nov 17 '17 at 10:15
  • Duplicated by: https://stackoverflow.com/questions/8242375/is-it-possible-to-call-async-page-load-in-asp-net-4-5 and https://stackoverflow.com/questions/34204450/call-async-method-in-page-load . Page_load a is naturally synchronous. If you want to optimize IIS throughput (like async controller approach in MVC/Web API), Page.RegisterAsyncTask, wan't make sense. Page.RegisterAsyncTask is more like manageable "fire-and-forget". – n.prokhorov Nov 17 '17 at 10:44

2 Answers2

15

Just because you can't await the result of a PageAsyncTask doesn't mean that the task itself can't kick off more functions that you can then await. You can take advantage of this to have an async page load.

public void Page_Load(object sender, EventArgs e)
{
    RegisterAsyncTask(new PageAsyncTask(PageLoadAsync));
}
 
public async Task PageLoadAsync()
{
    //perform your actions here, including calling async methods and awaiting their results

    Task<string> downloadTask = new WebClient().DownloadStringTaskAsync("http://www.example.com");

    TextBox1.Title = "We can do some actions while waiting for the task to complete";

    TextBox2.Title = await downloadTask;
}

Make sure your page is marked as async.

<%@ Page Language="C#" CodeBehind="Default.aspx.cs" Inherits="Default" Async="true" %>

Keep in mind that the above code is slightly misleading. ASP.NET Web Forms is still based on the HTTP request/response model. It can't actually update a textbox's title on the client side while waiting for some file to download. Instead, it updates the textbox's title in the HTTP response, and once all server side processing is done (including your asynchronous tasks) it will then send the response to the client, at which point they'll see the updated textbox's title.

mason
  • 31,774
  • 10
  • 77
  • 121
  • Thanks, this seems to be a good solution, however if I add arguments to my method, then PageAsyncTask doesn't accept it and gives me error of "Cannot convert Task to System.Func". I need the arguments as I have to process stuff before I post them to the API. – user65248 Nov 17 '17 at 14:51
  • @user65248 You're missing the point. Put the arguments directly in the PageLoadAsync method where you call your async methods. There is no need to actually pass arguments to PageLoadAsync. – mason Nov 17 '17 at 15:00
  • I did manage to run it by making a lambda function like this new Func(async () => await PageLoadAsync("Arguments"). However now I think it kind of Fire and Forget my task, I need it to pause page_load until the work is finished then continue loading other stuff, this way I can save stuff into the db based on the results. Maybe I am taking the wrong path here. – user65248 Nov 17 '17 at 15:22
  • @user65248 Again, you have missed the point. Take all the logic that used to be in your Page_Load (except for the async task registration I have shown) and move it into your PageLoadAsync. – mason Nov 17 '17 at 15:25
  • I get it now, thanks a lot, it all seem to be working fine now. – user65248 Nov 17 '17 at 17:11
0

As of VS2022 you need to use

Page.RegisterAsyncTask(....
Autonomic
  • 150
  • 4
  • 15