Как преобразовать .net 4.5 Пример Async/Await обратно в 4.0

Как выглядит код equivallent asp.net mvc 4.0?

using System.Net;
using System.Net.Http;
using System.Web.Mvc;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Web.Controllers
{
    public class HomeController : Controller
    {
        private HttpClient httpClient = new HttpClient();
        private static dynamic shots;

        public async Task<ActionResult> Index()
        {
            if (shots == null)
            {
                try
                {
                    var responseMessage = 
                       await httpClient.GetAsync
                            ("http://api.dribbble.com/shots/everyone?per_page=30");
                    responseMessage.EnsureSuccessStatusCode();

                    var value = await responseMessage.Content.ReadAsStringAsync();
                    shots = await JsonConvert.DeserializeObjectAsync<dynamic>(value);
                }
                catch (WebException)
                {
                }
            }
            return View(shots);
        }
    }
}

Ответы

Ответ 1

ПРИМЕЧАНИЕ: Это только для части Async/Await.

Самый простой способ - использовать Async CTP. Он имеет лицензию Go live, что означает, что вы можете использовать ее в производственном коде. Вы должны будете внести некоторые изменения в случаях, когда Async CTP не предоставляет эквиваленты async.

Вы можете использовать Async CTP на Azure, так как требуется только дополнительная DLL. Здесь есть аналогичный вопрос SOA Async CTP и поддержка Windows Azure

Я использую Async CTP в производстве более года без проблем. Я определенно рекомендую это. Обновление до .NET 4.5 довольно просто, по сути, требуя только некоторых изменений имени класса (TaskEx to Task) и нескольких изменений подписи.

Если вы можете использовать Visual Studio 2012 RC, вы также можете использовать Async Targeting pack, который позволит вам использовать ваш асинхронный код .NET 4 с меньшим количеством изменений, чем при использовании Async CTP.

Наконец, решение грубой силы должно использовать TaskIterator из образцов ParallelExtensionsExtras для эмуляции того, что делает async/await. Вам придется преобразовать все асинхронные вызовы в задачи или методы, возвращающие задачу, а затем перебирать список этих задач. Это намного больше кода, но это единственное решение, если вы не хотите использовать код CTP, даже если у него есть лицензия Go Live.

ParallelExtensionsExtras включают асинхронные задачи для WebClient, которые могут быть полезны, если вы решите переключиться с HttpClient на WebClient.

Ответ 2

Как кто-то изучает, как получить все это, работая в .NET 4.0, я также не нашел ответы на эту тему, а другие достаточно полно, чтобы немедленно встать и работать. Итак, более подробный ответ о том, что просто сделать:

======= ШАГ № 1) УСТАНОВКА Клиентских библиотек веб-API ASP.NET(RC) 4.0.20505.0 =======

http://nuget.org/packages/Microsoft.AspNet.WebApi.Client

PM> Install-Package Microsoft.AspNet.WebApi.Client

УСТАНОВКИ: System.Net.Http.dll, System.Net.Http.Formatting.dll, System.Net.Http.WebRequest.dll, Newtonsoft.Json.dll

======= ШАГ # 2) Библиотеки клиентских библиотек Microsoft.NET Framework 4 2.0.20505.0 =======

http://nuget.org/packages/Microsoft.Net.Http.

PM> Install-Package Microsoft.Net.Http.

Если вы уже выполнили шаг №1, NuGet должен был уже захватить эту зависимость: System.Net.Http.dll. System.Net.Http. это то, что обеспечивает HttpClient, HttpRequestMessage и HttpResponseMessage.

На этом этапе вы будете получать ошибки при использовании async/await (хотя эти ключевые слова все еще отображаются как ключевые слова), говоря такие вещи, как:

Невозможно найти все типы, требуемые модификатором 'async'. Ты таргетинг на неправильную версию фрейма или отсутствие ссылки на сборка?

Таким образом:

======= ШАГ № 3) Пакет асинхронного таргетинга для Visual Studio =======

http://www.microsoft.com/en-us/download/details.aspx?id=29576

PM> Install-Package Microsoft.CompilerServices.AsyncTargetingPack

('... Имя Visual Studio 11 необходимо обновить на NuGet, обе версии 1.0.0)

Устанавливает 1 dll: Microsoft.CompilerServices.AsyncTargetingPack.Net4.dll

"В" Async Targeting Pack для Visual Studio 2012 "предусмотрены проекты, предназначенные для .NET Framework 4.0 или Silverlight 5, для использования функции языка Async на С# 5... http://www.microsoft.com/en-us/download/details.aspx?id=29576

Помимо всего прочего, добавляет TaskEx (версия .NET 4.0, которая заполняет многие новые функции Task. TaskEx только для версии 4.0... поэтому .NET 4.5: "Task.Run" находится в 4.0: "TaskEx. Run", многие другие вещи похожи на эту библиотеку)

Внезапно ожидайте и асинхронно, и все работы начинают работать как шарм! Если вы задумаетесь, одна из самых важных вещей об этом - класс (объявленный без пространства имен): AsyncCompatLibExtensions. Статический класс, содержащий методы расширения, в частности: 1) Поток. Например. ReadAsync. Итак, теперь появляется stream.ReadAsync! (он на самом деле чисто обтекает поток BeginRead/BeginWrite, если вы хотите узнать), 2) WebClient. Например. webClient.DownloadStringTaskAsync и т.д.

Ответ 3

ПРЕДУПРЕЖДЕНИЕ Проверка ошибок не выполняется!

Хорошо, мне кажется, что я чему-то научился сегодня, прочитал эту статью http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx, чтобы узнать лучший способ справиться с этим:)

using System.Net.Http;
using System.Threading.Tasks;
using System.Web.Mvc;
using Newtonsoft.Json;
namespace DribbbleR.Web.Controllers
{
    public class HomeController : Controller
    {
        private static dynamic shots;
        private HttpClient client = new HttpClient();
        private string url = "http://api.dribbble.com/shots/everyone?per_page=30";

        public Task<dynamic> Index()
        {    if (shots == null)
             shots = Task.Factory.StartNew
                   (() => return DownloadContent();).Unwrap();    
             return shots;
        }
        public Task<dynamic> DownloadContent()
        {    var responseTask = client.GetAsync(url);
             var readTask = responseTask.ContinueWith
                 (t =>
                     {   t.Result.EnsureSuccessStatusCode();
                         return t.Result.Content.ReadAsStringAsync();
                      }
                  ).Unwrap();
            var deserializeTask = readTask.ContinueWith
                  (t => return JsonConvert.DeserializeObjectAsync<dynamic>(t.Result);)
            .Unwrap();
            var viewTask = deserializeTask.ContinueWith
                  (t =>  return this.View(t.Result););
            return viewTask;
        }
    }
}