2016-09-15 5 views
1

У меня есть метод async, который вызывает 3 разных API, чтобы получить некоторые данные, а затем отправить ответ на следующий API. Теперь на основании статьи Стивена Клири here избежать тупиковой ситуации:Использование ConfigureAwait (false) для частных методов async?

1 ваших «библиотека» асинхронные методы, использовать ConfigureAwait (ложь), где это возможно.
2. Не работает блок задач; используйте async полностью вниз.

Я хотел бы знать, верно ли то же самое для частных асинхронных методов? Нужно ли использовать ConfigureAwait(false), когда я вызываю метод асинхронизации private? Так что-то вдоль линии

public async Task<int> ProcessAsync(ServiceTaskArgument arg) 
    { 
     // do i need to use ConfigureAwait here while calling private async method? 
     var response1 = await GetAPI1().ConfigureAwait(false); 

     // do i need to use ConfigureAwait here while calling private async method? 
     var response2= await PostAPI2(response1).ConfigureAwait(false); 

     // do i need to use ConfigureAwait here while calling private async method? 
     await PostAPI3(response2).ConfigureAwait(false); 

     return 1; 
    } 

    private async Task<string> GetAPI1() 
    { 
     var httpResponse = await _httpClient.GetAsync("api1").ConfigureAwait(false); 

     // do i need to use ConfigureAwait here while calling private async method? 
     await EnsureHttpResponseIsOk(httpResponse).ConfigureAwait(false); 

     return await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); 
    } 

    private async Task<string> PostAPI2(string data) 
    { 
     var stringContent = new StringContent(data, Encoding.UTF8, "application/json"); 
     var httpResponse = await _httpClient.PostAsync("api2", stringContent).ConfigureAwait(false); 

     // do i need to use ConfigureAwait here while calling private async method? 
     await EnsureHttpResponseIsOk(httpResponse).ConfigureAwait(false); 

     return await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); 
    } 

    private async Task<string> PostAPI3(string data) 
    { 
     var stringContent = new StringContent(data, Encoding.UTF8, "application/json"); 
     var httpResponse = await _httpClient.PostAsync("api3", stringContent).ConfigureAwait(false); 

     // do i need to use ConfigureAwait here while calling private async method? 
     await EnsureHttpResponseIsOk(httpResponse).ConfigureAwait(false); 

     return await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); 
    } 

    private async Task EnsureHttpResponseIsOk(HttpResponseMessage httpResponse) 
    { 
     if (!httpResponse.IsSuccessStatusCode) 
     { 
      var content = await httpResponse.Content.ReadAsStringAsync().ConfigureAwait(false); 
      throw new MyHttpClientException("Unexpected error has occurred while invoking http client.", content, httpResponse.Headers); 
     } 
    } 

Update1
Кроме того, я прошел через SO отправлять here, но ответить предлагая использовать пользовательские NoSynchronizationContextScope.
Я хотел знать, нужно ли мне использовать ConfigureAwait (false) для частных методов или нет?

ответ

3

Я хотел знать, нужно ли мне использовать ConfigureAwait (false) для частных методов или нет?

Как правило, да. ConfigureAwait(false) следует использовать для каждыеawait, если только метод не нуждается в его контексте.

Однако, если вы используете NoSynchronizationContextScope, то это устраняет необходимость в ConfigureAwait(false).

+0

Эталонная реализация: http://stackoverflow.com/questions/28305968/use-task-run-in-synchronous-method-to-avoid-deadlock-waiting-on-async-method – Caramiriel

0

Это зависит от вашего класса. Является ли он частью библиотеки классов? Или это веб-api или другая служебная операция? Как сказал Стивен, безопаснее всего ConfigureAwait(false), чтобы избежать взаимоблокировок, но он также может добавить много ненужного кода, если вы абсолютно уверены, что вызывающий абонент не блокирует (.Wait() или .Result()), например, если ProcessAsync - это asp.net сеть api.

+2

Если вы действительно уверены, что код не нуждается в контексте, тогда добавление 'ConfigureAwait' предотвращает планирование каждого отдельного продолжения в контексте синхронизации. Даже если это не * тупик *, это будет влиять на производительность, а также потенциально задержать обработку операций, которые действительно нуждаются в этом контексте синхронизации. В частности, для библиотечных методов, которые, вероятно, будут использоваться много, хотя по крайней мере некоторые из этих применений чувствительны к производительности, это стоит делать. – Servy

+0

@Servy приятное дополнение. я продан :) – Kevin

+0

@Servy Спасибо. Как было предложено, я добавлю ConfigureAwaite (false). Но я действительно удивляюсь, почему это не стандартная реализация в .net.? – LP13