Как запустить пример кода MSDN Как создать предварительно вычисленные задачи?

Попытка запустить пример кода C# "Как создать предварительно вычисленные задачи" (MSDN) в .NET 4.0 Async CTP, внеся изменения:

  • Task.FromResult ---> TaskEx.FromResult
  • Task.FromResult ---> TaskEx.FromResult
  • Task.Run(async () => ---> TaskEx.RunEx(async () =>
    (также пробовал TaskEx.Run(async () =>)

но получаю ошибку компиляции:

Поскольку 'System.Func<System.Threading.Tasks.Task>' является асинхронным и возвращает задачу, ключевое слово return не должно сопровождаться выражением объекта.

Как изменить код, чтобы запустить этот пример?

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Threading.Tasks;

// Demonstrates how to use Task<TResult>.FromResult to create a task  
// that holds a pre-computed result. 
class CachedDownloads
{
  // Holds the results of download operations. 
  static ConcurrentDictionary<string, string> cachedDownloads =
     new ConcurrentDictionary<string, string>();

  // Asynchronously downloads the requested resource as a string. 
  public static Task<string> DownloadStringAsync(string address)
  {
    // First try to retrieve the content from cache. 
    string content;
    if (cachedDownloads.TryGetValue(address, out content))
    {

      return TaskEx //****** Task.FromResult ---> TaskEx.FromResult   
             .FromResult<string>(content);
    }

    // If the result was not in the cache, download the  
    // string and add it to the cache. 
    return TaskEx.RunEx //****** Task.Run  --> TaskEx.RunEx (TaskEx.Run)
      (async () =>    
    {
      content = await new WebClient().DownloadStringTaskAsync(address);
      cachedDownloads.TryAdd(address, content);
      return content;//*****Error
    });
  }

  static void Main(string[] args)
  {
    // The URLs to download. 
    string[] urls = new string[]
      {
         "http://msdn.microsoft.com",
         "http://www.contoso.com",
         "http://www.microsoft.com"
      };

    // Used to time download operations.
    Stopwatch stopwatch = new Stopwatch();

    // Compute the time required to download the URLs.
    stopwatch.Start();
    var downloads = from url in urls
                    select DownloadStringAsync(url);
    TaskEx.WhenAll(downloads)//*** Task.WhenAll -->  TaskEx.WhenAll
          .ContinueWith(results =>
    {
      stopwatch.Stop();

      // Print the number of characters download and the elapsed time.
      Console.WriteLine
            ("Retrieved {0} characters. Elapsed time was {1} ms."
              , results.Result.Sum(result => result.Length)
              , stopwatch.ElapsedMilliseconds);
    })
    .Wait();

    // Perform the same operation a second time. The time required 
    // should be shorter because the results are held in the cache.
    stopwatch.Restart();
    downloads = from url in urls
                select DownloadStringAsync(url);

    TaskEx.WhenAll(downloads)//*** Task.WhenAll -->  TaskEx.WhenAll
          .ContinueWith(results =>
    {
      stopwatch.Stop();

      // Print the number of characters download and the elapsed time.
      Console.WriteLine("Retrieved {0} characters. Elapsed time was {1} ms.",
         results.Result.Sum(result => result.Length),
         stopwatch.ElapsedMilliseconds);
    })
    .Wait();
  }
}

Обновление:

Выполняется ли этот пример кода без моих обновлений для Async CTP в .NET 4.5?


person Gennady Vanin Геннадий Вани&    schedule 07.05.2013    source источник
comment
Почему вы используете CTP теперь, когда доступна версия RTM? Это может быть ошибка в CTP, которая была исправлена.   -  person dlev    schedule 07.05.2013
comment
Поскольку RTM не устанавливается в Windows XP, а .NET 4.0 на машине с .NET 4.5 отличается от .NET 4.0 на машине без установленной версии 4.5.   -  person Gennady Vanin Геннадий Вани&    schedule 07.05.2013


Ответы (1)


Компилятор C# был улучшен в VS2012, чтобы быть более интеллектуальным в отношении универсального разрешения перегрузок при наличии async лямбда-выражений (т. е. Func<Task> и семейства). Поскольку вы используете VS2010, вам придется помогать ему здесь и там.

Подсказка заключается в типе вашей лямбды async, как показано в вашем сообщении об ошибке: System.Func<System.Threading.Tasks.Task>.

должно быть System.Func<System.Threading.Tasks.Task<System.String>>.

Итак, я бы попробовал это:

return TaskEx.RunEx<string> //****** Task.Run  --> TaskEx.RunEx (TaskEx.Run)
  (async () =>    
{
  content = await new WebClient().DownloadStringTaskAsync(address);
  cachedDownloads.TryAdd(address, content);
  return content;//*****Error
});
person Stephen Cleary    schedule 07.05.2013