3

you will see a console app codes below. There are two situations I tried. In the first case, I commented await GetProducts() line. In this case, output is:

Start Time: 13:20:30 Job started... Finish Time: 13:20:30 Job finished...

In second case, I opened await GetProducts line and commented await Task.Run...lines. In this case, output is:

Start Time: 13:19:33 Job started... Job finished... Finish Time: 13:19:43

Here are the code lines...What is the difference? Thanks...

class Program
{
    static void Main(string[] args)
    {
        Task x = LoadProductsAsync();

        Console.Read();
    }


    private static async Task LoadProductsAsync()
    {
        Console.WriteLine("Start Time: "  + DateTime.Now.ToLongTimeString());

        //await GetProducts();

        await Task.Run(() =>
        {
            GetProducts();
        });

        Console.WriteLine("Finish Time: " + DateTime.Now.ToLongTimeString());
    }

    private static Task<List<Product>> GetProducts()
    {
        return Task.Factory.StartNew(
            () => GetProductsByCategory()
        );
    }

    private static List<Product> GetProductsByCategory()
    {
        Console.WriteLine("Job started...");

        System.Threading.Thread.Sleep(10000);

        Console.WriteLine("Job finished...");

        return new List<Product>();

    }
}
Jamie Rees
  • 7,973
  • 2
  • 45
  • 83
qwerty
  • 31
  • 2
  • You might want to read http://blog.stephencleary.com/2013/08/startnew-is-dangerous.html and http://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-using.html. – GSerg Apr 26 '16 at 10:53
  • I think, my version would have been very useful for the web application. Think about a web page that loads large data set from database in form_load method. In this case, the page waits for database operation. But in my version, a page can be displayed without getting dataset. Am I right? – qwerty Apr 27 '16 at 11:10
  • No, you are not right. Page will only be sent out when the data is fetched. `async` is used in ASP.NET [for a different reason](http://stackoverflow.com/q/15190112/11683). – GSerg Apr 27 '16 at 11:48

2 Answers2

6

This is the problem:

await Task.Run(() =>
{
    GetProducts();
});

You're not waiting for the task returned by GetProducts() to complete - you're just waiting for the immediate GetProducts() method call to complete.

The simplest fix to that is to use a method group conversion instead, and call Task.Run<TResult>(Func<Task<TResult>>):

await Task.Run(GetProducts);

Then the task returned by Task.Run will be a proxy task for the task returned by GetProducts(), so the await expression won't complete until GetProducts has really finished.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I think, my version would have been very useful for the web application. Think about a web page that loads large data set from database in form_load method. In this case, the page waits for database operation. But in my version, a page can be displayed without getting dataset. Am I right? – qwerty Apr 27 '16 at 11:08
  • 1
    @qwerty: Not really - you don't have anywhere for the results to end up. If you want to load the data after the page, you'd do that with Javascript in the client. – Jon Skeet Apr 27 '16 at 11:24
-2

Change your code to snnipet below. And your code will be the same.

await Task.Run(() =>
    {
        GetProductsByCategory();
    });

Your last code was like (you run task in task):

await Task.Run(() =>
    {
        return Task.Factory.StartNew(
            () => GetProductsByCategory()
        );
    });