Skip to main content
Post Closed as "Duplicate" by Servy, Peter Duniho c#
added 4 characters in body
Source Link
Jonas T
  • 3.1k
  • 4
  • 35
  • 45

I know some people will argue "why don't you just make SyncMethod() to async method?". We wish, but in a real world, sometimes we have to keep SyncMethod the way it is for backwards compatibility reasons.

Here is the situation. We have a deadlock with the following code.

public void SyncMethod() { var serviceResult = ProcessDataAsync().Result; } public await ServiceResult ProcessDataAsync() { //Do other things await GetDataFromApiAsync(); } private static HttpClient Client = new HttpClient(); public await ApiResult GetDataFromApiAsync() { var response = await Client.GetAsync("http://api.com/getJson"); dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); return obj; } 

Option 1: Use Task.Run and get task.Result. This solves the deadlock issue but it's forced to run in a new thread, outside of the synchronization context of the originating thread. However, there's certain environments where this is very ill-advised: particularly web applications. isIs it a good practice?

public void SyncMethod() { Task<decimal> task = Task.Run<decimal>(async () => await ProcessDataAsync()); var serviceResult = task.Result; } 

Optoin 2: add ConfigureAwait(false) all the way down from Sync to the last async method.

public void SyncMethod() { var serviceResult = GetDataFromApiAsync().ConfigureAwait(false).GetAwaiter().GetResult();; } public await ServiceResult ProcessDataAsync() { //Do other things await GetDataFromApiAsync().ConfigureAwait(false); } private static HttpClient Client = new HttpClient(); public await ApiResult GetDataFromApiAsync() { var response = await Client.GetAsync("http://api.com/getJson").ConfigureAwait(false); dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); return obj; } 

Option 3Option 3: Stephen Cleary's answer.

public void SyncMethod() { var serviceResult = GetDataFromApiAsync().(sync: true).GetAwaiter().GetResult(); } 

All these solutions will solve the deadlock issue. My question is what the best practice would be?

I know some people will argue "why don't you just make SyncMethod() to async method?". We wish, but in a real world, sometimes we have to keep SyncMethod the way it is.

Here is the situation. We have deadlock with the following code.

public void SyncMethod() { var serviceResult = ProcessDataAsync().Result; } public await ServiceResult ProcessDataAsync() { //Do other things await GetDataFromApiAsync(); } private static HttpClient Client = new HttpClient(); public await ApiResult GetDataFromApiAsync() { var response = await Client.GetAsync("http://api.com/getJson"); dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); return obj; } 

Option 1: Use Task.Run and get task.Result. This solves the deadlock issue but it's forced to run in a new thread, outside of the synchronization context of the originating thread. However, there's certain environments where this is very ill-advised: particularly web applications. is it a good practice?

public void SyncMethod() { Task<decimal> task = Task.Run<decimal>(async () => await ProcessDataAsync()); var serviceResult = task.Result; } 

Optoin 2: add ConfigureAwait(false) all the way down from Sync to the last async method.

public void SyncMethod() { var serviceResult = GetDataFromApiAsync().ConfigureAwait(false).GetAwaiter().GetResult();; } public await ServiceResult ProcessDataAsync() { //Do other things await GetDataFromApiAsync().ConfigureAwait(false); } private static HttpClient Client = new HttpClient(); public await ApiResult GetDataFromApiAsync() { var response = await Client.GetAsync("http://api.com/getJson").ConfigureAwait(false); dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); return obj; } 

Option 3: Stephen Cleary's answer.

public void SyncMethod() { var serviceResult = GetDataFromApiAsync().(sync: true).GetAwaiter().GetResult(); } 

All these solutions will solve the deadlock issue. My question is what the best practice would be?

I know some people will argue "why don't you just make SyncMethod() to async method?". We wish, but in a real world, sometimes we have to keep SyncMethod the way it is for backwards compatibility reasons.

Here is the situation. We have a deadlock with the following code.

public void SyncMethod() { var serviceResult = ProcessDataAsync().Result; } public await ServiceResult ProcessDataAsync() { //Do other things await GetDataFromApiAsync(); } private static HttpClient Client = new HttpClient(); public await ApiResult GetDataFromApiAsync() { var response = await Client.GetAsync("http://api.com/getJson"); dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); return obj; } 

Option 1: Use Task.Run and get task.Result. This solves the deadlock issue but it's forced to run in a new thread, outside of the synchronization context of the originating thread. However, there's certain environments where this is very ill-advised: particularly web applications. Is it a good practice?

public void SyncMethod() { Task<decimal> task = Task.Run<decimal>(async () => await ProcessDataAsync()); var serviceResult = task.Result; } 

Optoin 2: add ConfigureAwait(false) all the way down from Sync to the last async method.

public void SyncMethod() { var serviceResult = GetDataFromApiAsync().ConfigureAwait(false).GetAwaiter().GetResult();; } public await ServiceResult ProcessDataAsync() { //Do other things await GetDataFromApiAsync().ConfigureAwait(false); } private static HttpClient Client = new HttpClient(); public await ApiResult GetDataFromApiAsync() { var response = await Client.GetAsync("http://api.com/getJson").ConfigureAwait(false); dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); return obj; } 

Option 3: Stephen Cleary's answer.

public void SyncMethod() { var serviceResult = GetDataFromApiAsync().(sync: true).GetAwaiter().GetResult(); } 

All these solutions will solve the deadlock issue. My question is what the best practice would be?

Source Link
Jonas T
  • 3.1k
  • 4
  • 35
  • 45

What is the best practice to call Async method from Sync method?

I know some people will argue "why don't you just make SyncMethod() to async method?". We wish, but in a real world, sometimes we have to keep SyncMethod the way it is.

Here is the situation. We have deadlock with the following code.

public void SyncMethod() { var serviceResult = ProcessDataAsync().Result; } public await ServiceResult ProcessDataAsync() { //Do other things await GetDataFromApiAsync(); } private static HttpClient Client = new HttpClient(); public await ApiResult GetDataFromApiAsync() { var response = await Client.GetAsync("http://api.com/getJson"); dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync()); return obj; } 

Option 1: Use Task.Run and get task.Result. This solves the deadlock issue but it's forced to run in a new thread, outside of the synchronization context of the originating thread. However, there's certain environments where this is very ill-advised: particularly web applications. is it a good practice?

public void SyncMethod() { Task<decimal> task = Task.Run<decimal>(async () => await ProcessDataAsync()); var serviceResult = task.Result; } 

Optoin 2: add ConfigureAwait(false) all the way down from Sync to the last async method.

public void SyncMethod() { var serviceResult = GetDataFromApiAsync().ConfigureAwait(false).GetAwaiter().GetResult();; } public await ServiceResult ProcessDataAsync() { //Do other things await GetDataFromApiAsync().ConfigureAwait(false); } private static HttpClient Client = new HttpClient(); public await ApiResult GetDataFromApiAsync() { var response = await Client.GetAsync("http://api.com/getJson").ConfigureAwait(false); dynamic obj = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync().ConfigureAwait(false)); return obj; } 

Option 3: Stephen Cleary's answer.

public void SyncMethod() { var serviceResult = GetDataFromApiAsync().(sync: true).GetAwaiter().GetResult(); } 

All these solutions will solve the deadlock issue. My question is what the best practice would be?