Вопрос

I am trying to learn/understand more about async/await in C# and I would put myself in rookie category so all your comments/suggestions are welcome. I wrote small test to have better understanding and clarification about await/async. My program freezes after "GetStringLength" call I tried reading several things but looks like I am stuck and I thought of taking expert opinion on what I might be doing wrong. Can you please guide me or point me in right direction here?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncPatterns
{
    class Program
    {
        static void Main(string[] args)
        {
            Program p = new Program();
            Task<string> url = p.FindLargtestWebPage(new Uri[]{new Uri("http://www.google.com"), 
                                                            new Uri("http://www.facebook.com"), 
                                                            new Uri("http://www.bing.com") });
            Console.WriteLine(url.Result);
            Console.ReadLine();
        }

        public async Task<string> FindLargtestWebPage(Uri[] uris)
        {
            string highCountUrl = string.Empty;
            int maxCount = 0;

            foreach (Uri uri in uris)
            {
                Console.WriteLine(string.Format("Processing {0}", uri.ToString()));
                var pageContent = await GetWebPageString(uri);
                var count = await GetStringLength(pageContent);
                if (count > maxCount)
                {
                    highCountUrl = uri.ToString();
                }
            }
            return highCountUrl;            
        }

        public async Task<int> GetStringLength(string pageData)
        {
            Console.WriteLine("Getting length");
            return await new Task<int>(() =>
            {
                return pageData.Length;
            });
        }

        public async Task<string> GetWebPageString(Uri uri)
        {
            WebClient webClient = new WebClient();
            Console.WriteLine("Downloading string");
            return await webClient.DownloadStringTaskAsync(uri.ToString());
        }

    }
}
Это было полезно?

Решение 2

The culprit for freezing is this:

return await new Task<int>(() =>
{
    return pageData.Length;
});

This Task constructor doesn't start the task, so you're creating a Task that isn't running. When you await on it in GetStringLength you're going to be waiting forever for the result.

You can either start the task manually:

var result = new Task<int>(() =>
{
    return pageData.Length;
});

result.Start();

return result;

or use the Task.Run static method, which will create and start the task:

return Task.Run(() =>
{
    return pageData.Length;
});

Другие советы

Do not use the Task constructor in async code, and only use async when you have asynchronous work to do. GetStringLength has no asynchronous work to do, so it should be:

public int GetStringLength(string pageData)
{
  Console.WriteLine("Getting length");
  return pageData.Length;
}

For more information, see my async/await intro.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top