Azure Storage Tables: Waiting Table. ExecuteAsync (InsertOperation) executes but never ends

Well, my problem is that the call expects table.ExecuteAsync (...) in the Azure storage table inserts the requested data, but never ends (does not return TableResult). The same case with InsertOrUpdate and Update operations. I also tried different tables with different number of properties - the same problem.

When I call table.Execute (...) - everything works fine for all kinds of operations.

Here my code is simple:

External call (it is placed in the MVC controller in the async action):

List<Task<ServiceResult<Boolean?>>> addPostTasks = new List<Task<Common.ServiceResult<bool?>>>(); foreach (var userStream in userStreams) { Task<ServiceResult<Boolean?>> addPostTask = postsStorageSvc.AddImagePost(...); postsAddImagePostTasks.Add(addPostTask); } Task.WaitAll(addPostTasks.ToArray()); 

The method is called:

 public async Task<ServiceResult<Boolean?>> AddImagePost(...) { ServiceResult<Boolean?> result = new ServiceResult<bool?>(null); try { PostTableEntity newPost = new PostTableEntity(streamId.ToString(), Guid.NewGuid().ToString(), creatorId, date, htmlText); TableOperation insertOperation = TableOperation.Insert(newPost); //Following line never ends! TableResult tableResult = await this._storageTableBootstrapper.Table.ExecuteAsync(insertOperation); //Following line works perfect - but is not ASYNC TableResult tableResult = this._storageTableBootstrapper.Table.Execute(insertOperation); } catch (Exception ex) { result.Result = false; result.Errors.Add("AzurePostsStorageService Unexpected error: " + ex.Message); } return result; } 
+5
source share
3 answers

The problem is here:

 Task.WaitAll(addPostTasks.ToArray()); 

Your asynchronous method tries to translate itself back into the ASP.NET synchronization context, which gets stuck because you initiated a blocking call with Task.WaitAll .

Instead, you will need to follow the async all the way pattern and use Task.WhenAll and await for this:

 await Task.WhenAll(addPostTasks.ToArray); 

Stefan Cleary describes this in detail on his blog (which @NedStoyanov added):

Another important point: the ASP.NET request context is not tied to a specific thread (for example, the user interface context), but it does only allow one thread at a time. This interesting aspect is not officially documented by AFAIK, but is mentioned in my MSDN article on SynchronizationContext.

+9
source

This is the classic dead end caused by this line:

 Task.WaitAll(addPostTasks.ToArray()); 

try changing it to:

 await Task.WhenAll(addPostTasks.ToArray()); 

Basically, Task.WaitAll blocks the flow of requests and cannot continue the Tasks initiated by await table.ExecuteAsync(...) . Another alternative is to use ConfigureAwait(false) for internal tasks to avoid switching SynchronizatonContext .

 await table.ExecuteAsync(...).ConfigureAwait(false); 

You can use ConfigureAwait(false) if you do not need to switch to the original SynchronizationContext . In your case, I believe that you can do this with all the expectations, as you are on the server, and it does not matter if the code is executed after await in the thread pool or not.

See this article for more information: msdn.microsoft.com/enus/magazine/jj991977.aspx

+4
source

If you work in an organization, there may be a problem with the proxy settings that are enabled in your organization. I had a similar problem and I used the following steps to solve it:

1: Add the following code to Configure at startup.cs

 app.UseDeveloperExceptionPage(); var webProxy = new WebProxy(new Uri(Configuration["defaultProxy:proxyaddress"]), BypassOnLocal: false); var proxyHttpClientHandler = new HttpClientHandler { Proxy = webProxy, UseProxy = true, }; AppContext.SetSwitch("System.Net.Http.UseSocketsHttpHandler", false); 

2: add to appsettings.json

 "defaultProxy": { "proxyaddress": "<your IP here>" }, 
0
source

Source: https://habr.com/ru/post/1212095/


All Articles