Как создать асинхронный метод в C # 4 в соответствии с лучшими практиками? - PullRequest
14 голосов
/ 16 ноября 2010

Рассмотрим следующий фрагмент кода:

public static Task<string> FetchAsync()
{
    string url = "http://www.example.com", message = "Hello World!";

    var request = (HttpWebRequest)WebRequest.Create(url);
    request.Method = WebRequestMethods.Http.Post;

    return Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null)
        .ContinueWith(t =>
        {
            var stream = t.Result;
            var data = Encoding.ASCII.GetBytes(message);
            Task.Factory.FromAsync(stream.BeginWrite, stream.EndWrite, data, 0, data.Length, null, TaskCreationOptions.AttachedToParent)
                .ContinueWith(t2 => { stream.Close(); });
        })
        .ContinueWith<string>(t =>
        {
            var t1 =
                Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null)
                .ContinueWith<string>(t2 =>
                {
                    var response = (HttpWebResponse)t2.Result;
                    var stream = response.GetResponseStream();
                    var buffer = new byte[response.ContentLength > 0 ? response.ContentLength : 0x100000];
                    var t3 = Task<int>.Factory.FromAsync(stream.BeginRead, stream.EndRead, buffer, 0, buffer.Length, null, TaskCreationOptions.AttachedToParent)
                        .ContinueWith<string>(t4 =>
                        {
                            stream.Close();
                            response.Close();
                            if (t4.Result < buffer.Length)
                            {
                                Array.Resize(ref buffer, t4.Result);
                            }
                            return Encoding.ASCII.GetString(buffer);
                        });
                    t3.Wait();
                    return t3.Result;
                });
            t1.Wait();
            return t1.Result;
        });
}

Он должен возвращать Task<string>, отправлять HTTP-запрос POST с некоторыми данными, возвращать результат с веб-сервера в виде строки и быть максимально эффективным..

  • Обнаружили ли вы проблемы с асинхронным потоком в приведенном выше примере?
  • Можно ли использовать .Wait () внутри .ContinueWith () в этом примере
  • Видите ли вы какие-либо другие проблемы с этим кодом (за исключением обработки исключений)?

Ответы [ 2 ]

3 голосов
/ 16 ноября 2010

Если код C # 4.0, связанный с асинхронностью, равен огромен и безобразен - есть вероятность, что он реализован правильно.Если он хороший и короткий, то, скорее всего, это не так;)

.. хотя, вы можете сделать его более привлекательным, создав методы расширения в WebRequest, классах Stream и очистив метод main.

PS : Я надеюсь, что C # 5.0 с его новым ключевым словом async и библиотека скоро будет выпущен.

Ссылка : http://msdn.microsoft.com/en-us/vstudio/async.aspx

0 голосов
/ 16 ноября 2010

Вы правы, считая, что Ожидания не нужны - Результат будет блокироваться, пока результат не будет готов.


Однако, еще более простым способом было бы использовать его на основе примеров, представленных в библиотеке ParallelExtensionsExtras .

Они сделали расширения для WebClient, которые делают точно то, что вы ищете:

static Task<string> FetchAsync()
{
    string url = "http://www.example.com", message = "Hello World!";

    return new WebClient().UploadStringTask(url, "POST", message);
}

Подробнее об этом можно прочитать в этой публикации в блоге «Параллельное программирование с .NET» .

...