0

я в настоящее время следующие:Выполняется ли это асинхронно?

var tasks = new List<Task>(); 

foreach (myObject obj in myObjectList) 
{ 
    tasks.Add(downloadBitmap(obj.profilePath, obj.id)); 
} 

await Task.WhenAll(tasks); 

downloadBitmap

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
RequestState myRequestState = new RequestState(); 
myRequestState.request = request; 

// Start the asynchronous request. 
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(RespCallback), Tuple.Create(myRequestState, actorID)); 

// this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted 
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), request, DefaultTimeout, true); 

// The response came in the allowed time. The work processing will happen in the 
// callback function. 
allDone.WaitOne(); 

RespCallBack

 Tuple<RequestState, int> state = (Tuple<RequestState, int>)asynchronousResult.AsyncState; 
     RequestState myRequestState = state.Item1; 
     int actorID = state.Item2; 

     try 
     { 
      HttpWebRequest myHttpWebRequest = myRequestState.request; 
      myRequestState.response = (HttpWebResponse)myHttpWebRequest.EndGetResponse(asynchronousResult); 

      // Read the response into a Stream object. 
      Stream responseStream = myRequestState.response.GetResponseStream(); 
      myRequestState.streamResponse = responseStream; 
      Bitmap bitmap = new Bitmap(responseStream); 

      // Do some work here 

     } 
     catch (WebException e) 
     { 
      Console.WriteLine("\nRespCallback Exception raised!"); 
      Console.WriteLine("\nMessage:{0}", e.Message); 
      Console.WriteLine("\nStatus:{0}", e.Status); 
     } 
     finally 
     { 
      // Release the HttpWebResponse resource. 
      myRequestState.response.Close(); 
     } 
     allDone.Set(); 

Я получил большую часть этого из MSDN сайта. Я также получать предупреждение:

This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.

для функции DownloadBitmap.

Я понимаю, что я не использую await в этой функции, но причина, я думал, что это не было необходимо в любом месте потому, что BeginGetResponse уже asynchronous?

Не уверен, что, если мое понимание этого совершенно правильно ...

+1

В этом методе вы запускаете асинхронный вызов с 'request.BeginGetResponse'. Но ваш текущий поток блокируется при вызове 'allDone.WaitOne();' и он только бодрствует, когда 'другой поток 'выбирается для обработки асинхронного результата и вызывает' allDone.Set(); '. Это не правильный способ реализации asynch. Вы можете взглянуть на: http://stackoverflow.com/questions/10565090/getting-the-response-of-a-asynchronous-httpwebrequest –

+0

Ваше использование шаблона APM вместе с WaitHandle не имеет смысла. Просто используйте 'wait WebRequest.GetResponseAsync'. Вы уже ждали. Почему все это сложное вещество APM? – usr

+0

Кроме того, это не является хорошим вопросом для переполнения стека. Это стена кода, которая нуждается в проверке. – usr

ответ

0

Я понимаю, что я не использую await в этой функции, но причина я подумал, что не надо было в любом месте потому, что BeginGetResponse является уже асинхронный?

Вы правы, вы не нужно использовать async ключевое слово, потому что вы после различных рисунка, который также является асинхронным. Единица с BeginXXX и EndXXX называется APM (Asynchronous Programming Model). async-await идет рука об руку с более новым рисунком, который называется TAP (Task-based Asynchronous Pattern).

Если вы решите пойти с TAP, существует намного более простой способ достичь того, что вы пытаетесь сделать.

В этом случае нет необходимости в каких-либо примитивах синхронизации. Использование существующей TAP APIs, которые существуют в HttpClient вместо:

public async Task<Bitmap> DownloadBitmapAsync(string uri) 
{ 
    var httpClient = new HttpClient(); 
    var response = await httpClient.GetAsync(uri); 
    using (var responseStream = await response.Content.ReadAsStreamAsync()) 
    { 
     return new Bitmap(responseStream); 
    } 
} 

, а затем выполнить их все одновременно:

var bitmapDownloadTasks = myObjectList.Select(obj => 
               DownloadBitmapAsync(obj.profilePath)); 
await Task.WhenAll(bitmapDownloadTasks); 

Примечание я упал один из параметров, как я не мог увидеть подпись метода для вашего downloadBitmap метод.

Таким образом, вы используете существующий TAP apis вместо того, чтобы создавать их самостоятельно с помощью обертки над шаблоном APM. Это может сэкономить несколько строк кода и может уменьшить частоту вашего кода.

+1

Цените свои объяснения и примеры! –

1

BeginGetResponse является асинхронным, однако он использует старую парадигму асинхронного программирования в .NET называется Asynchronous Programming Model или (APM). Async-await использует более новый способ выполнения асинхронного программирования, основанный на Task Based Asynchronous Pattern.

Подробнее о шаблонах программирования асинхронов можно узнать больше here.

Существует способ конвертировать из более старого API, поддерживающего APM, в новый с помощью метода TaskFactory.FromAsync, чтобы преобразовать ваш метод в async.

Я думаю, что вам нужно что-то вроде этого:

myRequestState.response = 
     await TaskFactory.FromAsync(
         request.BeginGetResponse, 
         request.EndGetResponse, 
         Tuple.Create(myRequestState, actorID)); 
0

Если вы используете .NET 4.5 или выше, предпочтительный метод для использования на HttpWebRequest объекта будет GetResponseAsync() см here

Так ваш веб-вызов будет выглядеть примерно так:

//note the use of the async/await 
public async Task<Bitmap> DownloadBitmap(/* whatever your params were */) 
{ 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
    //add the rest of the data/params or anything else you need then... 
    // await the asynchronous request. 

    HttpWebResponse result = (HttpWebResponse)(await request.GetResponseAsync()); 

    Stream responseStream = myWebResponse.GetResponseStream(); 
    return new Bitmap(responseStream); 
} 

и назвать его так:

var bitmaps = new List<Bitmap>(); 

foreach (myObject obj in myObjectList) 
{ 
    bitmaps.Add(await DownloadBitmap(obj.profilePath, obj.id)); 
} 

Если вы не хотите ждать, вы сможете это сделать (или для .NET 4.0+):

//note the use of the the slightly older ContinueWith 
public Task<Bitmap> DownloadBitmap(/* whatever your params were */) 
{ 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); 
    //add the rest of the data/params or anything else you need then... 
    // await the asynchronous request. 

    return request.GetResponseAsync().ContinueWith((antecedent) => { 
     HttpWebResponse myWebResponse = (HttpWebResponse)antencedent.Result; 
     Stream responseStream = myWebResponse.GetResponseStream(); 
     return new Bitmap(responseStream); 
    }); 
} 

и назвать его так:

var tasks = new List<Task>(); 

foreach (myObject obj in myObjectList) 
{ 
    tasks.Add(DownloadBitmap(obj.profilePath, obj.id)); 
} 

await tasks.WhenAll(); 

Но это не совсем то, что вы просите, вы спрашиваете о методе быть асинхронным или нет, используя APM (Асинхронная модель программирования) из IAsyncCallbacks и IAsyncResults является проблематичной, поскольку он требует, чтобы вручную настроить ожидания и состояние и как source

TPL (Task Parallel Library) вводит шаблон TAP (на основе задач асинхронного Pattern) очищает и обрабатывает много тяжелого подъема для вас, обертывая управление ожиданием и состоянием с помощью Lambda Expressions и объекта Task (мой второй пример).

Это может быть сделано еще одним шагом в .NET 4.5, позволяя непосредственно await объекту Task. вместо того, чтобы называть Task.Result (что может быть проблематичным, поскольку исключения, которые происходят в вашем объекте Task, завернуты в объект AggregateException, который вы должны развернуть/свернуть, чтобы посмотреть, что на самом деле произошло).

С помощью async/await в TAP вы снова пользуетесь функциями, встроенными в язык, который автоматически ожидает выполнения задачи и возвращает результат, или в случае исключения, автоматически разворачивает исключение и бросает это для вас, как обычный синхронный метод. (Это больше, чем это, но что касается разъяснений на высшем уровне, это так просто - см. here для получения более подробной информации.)

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

Наконец, на самом деле ответить на этот вопрос - да акт использования BeginGetResponseявляется асинхронный, однако, это не вызов, который вы можете ждать, потому что использует обратные вызовы, а не возвращать объект Ждите.

Так что, пока вы не включили его в свой вопрос, я предполагаю, что у вас есть подпись метода для DownloadBitmap так: public async Task DownloadBitmap(/* args */) однако вы ничего не ожидаете в этом методе, потому что шаблон APM не напрямую выставить дескриптор ожидания.

Если вы хотите дождаться задач (предпочтительный метод для .NET в эти дни), рассмотрите возможность использования другого асинхронного шаблона.

Из MSDN:

Асинхронная модель программирования (АПМ) шаблон (называемый также шаблон IAsyncResult), где асинхронные операции требуют Begin и методы End (например, BeginWrite и EndWrite для асинхронных операций записи). Этот шаблон больше не рекомендуется для новой разработки. Для получения дополнительной информации см. Модель асинхронного программирования (APM).

Асинхронный шаблон на основе событий (EAP), который требует метода с суффиксом Async, а также требует одного или нескольких событий, типов делегатов обработчика событий и типов, созданных EventArg. EAP был представлен в .NET Framework 2.0. Он больше не рекомендуется для новой разработки. Для получения дополнительной информации см. Асинхронный шаблон на основе событий (EAP).

Асинхронный шаблон на основе задач (TAP), который использует один метод для представления инициирования и завершения асинхронной операции. TAP был представлен в .NET Framework 4 и является рекомендуемым подходом к асинхронному программированию в .NET Framework. Асинхронные и ожидающие ключевые слова в C# и операторы Async и Await на языке Visual Basic добавляют поддержку языка TAP. Для получения дополнительной информации см. Асинхронный шаблон на основе задач (TAP).