1

I want to create a async method which will open a thread and complete several tasks that is relatively independent to the current http request (for example, sending emails and generating files both of which takes time)

I created the following method

private static async Task<T> DoSeparateTask<T>(Func<T> func)
{
    return func();
}

and want to use it in such a way:

private static void DoSomething()
{
    #step 1 - some code for immediate processing
    #step 2 - some code for generating documents which takes time
    var additionalDocumentGenerationWork = DoSeparateTask<Document>(() =>{
        #additional code for generating Document
       #even though it returns Document, but 99% time it wont be used in this method
    });
    #step 3 - some code for sending SMTP email which takes time
    var additionalDocumentGenerationWork = DoSeparateTask<bool>(() =>{
        #additional code for sending email
        return true;
    });

}

Everything compiles, however when I run the web application, it still keeps loading and waiting everything to complete before rendering the web page. As the 2 additional tasks (email and documents) are not relevant for displaying the webpage, how can I achieve such by using the async modifiers?

Or if my understanding of async is wrong... please help me to correct...

Many thanks.

1
  • You should look at the warning that the compiler is giving you, for that async method that does not have any await statement in it. Commented Nov 13, 2014 at 19:20

2 Answers 2

3

Or if my understanding of async is wrong... please help me to correct...

As I explain on my blog, async does not change the HTTP protocol. At the end of the day, you only have one response for each request. To put another way, async yields to the thread pool, not to the client.

What you're looking for is a way to do operations outside the request/response lifecycle, which is not directly supported by ASP.NET. I describe a few approaches on my blog. The best (most reliable) approach is to place the work into a queue, and have an independent backend that processes the queue (such as an Azure worker role).

Sign up to request clarification or add additional context in comments.

2 Comments

What Stephen wrote is spot on, here are a few more options that you can choose from to solve this problem, hanselman.com/blog/HowToRunBackgroundTasksInASPNET.aspx
Thank you very much Stephen - it gives me clear direction of what to be done - because each document and email can be easily processed within 1 minute so I have adapted .NET framework 4.5.2 HostingEnvironment.QueueBackgroundWorkItem() as you suggested in the blog. It works amazingly!
0

You don't need the DoSeparateTask<T>() method. Instead, just use Task.Run<T>():

private static async Task DoSomething()
{
    // #step 1 - some code for immediate processing
    // #step 2 - some code for generating documents which takes time
    var additionalDocumentGenerationWork1 = await Task.Run(() =>
    {
        // #additional code for generating Document
        // #even though it returns Document, but 99% time it wont be used in this method
    });

    // #step 3 - some code for sending SMTP email which takes time
    var additionalDocumentGenerationWork2 = await Task.Run(() =>
    {
        // #additional code for sending email
        return true;
    });
}

Note that the type of additionalDocumentGenerationWork1 and additionalDocumentGenerationWork2 (you used the same name twice in your example, so I changed it above to make the code legal) are Document and bool respectively. You can use additionalDocumentGenerationWork1 in your second task invocation if you like (e.g. to pass the result of the first operation).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.