BUG in Cells .NET SDK - Aysnc/Await deadlock issue

Hello,

The .NET SDK for Aspose.Cells-Cloud (v 24.9.0) has deadlock issues caused by the current aysnc/await implementation.

The issue is easily reproduced with a Windows Forms or ASP.NET project, I tested on .NETFramework 4.5.2, .net standard 2.0 and net6.0. The good news is it’s easily fixed (example below).

This affects Windows Forms and ASP.NET projects, it does not effect .NET console applications because there is no UI or Request context (which causes the deadlock)

Read here for a good explanation, a blog post written by Microsoft MVP who literally wrote the book on concurrency in C#.

In brief, if your helper methods are async, then your requesting thread must also await or else you’ll have a deadlock situation with the UI or Request context.

Take for example Aspose.Cells.Cloud.SDK.Api.CellsApi.DeleteFolder()

The DeleteFolder() has helper functions that use async/await several levels deep (for example ApiInvoker.cs → GetResponseAsync()), yet DeleteFolder() itself is not async, so you have the classic deadlock case the linked article above refers to.

With minor modifications to CellsApi.cs this can be resolved by making the public methods awaitable. For example DeleteFolder() becomes

public  async Task<string> DeleteFolder(DeleteFolderRequest request)
{
    requestHandlers.ForEach(p => p.ProcessUrl(""));
    var result = await invoker.InvokeApiAsync<  string  >(request.CreateHttpRequest(BaseUri +"/" +Version, this.invoker.DefaultHeaderMap, this.requestHandlers));
    return result;
}

Then you can await DeleteFolder() in your UI or Request context and it works as expected.

Let me know if you’d like more information, examples, but this is easily reproduced and fixed. I use your other .NET SDKs, including Words Cloud, PDF Cloud and the async/await is implemented differently / correctly, thus no issues with deadlock.

Another example in CellsApi.cs

  'turning this:
  public SaveResponse  PostWorkbookSaveAs(PostWorkbookSaveAsRequest request)
  {
      RequestHandlers.ForEach(p >= p.ProcessUrl(""));
      var result = Invoker.InvokeApiAsync < SaveResponse > (Request.CreateHttpRequest(BaseUri + "/" + Version, this.invoker.DefaultHeaderMap, this.requestHandlers)).Result;
      return result;
  }

  'into this:
  public async Task<SaveResponse> PostWorkbookSaveAs(PostWorkbookSaveAsRequest request)
  {
      RequestHandlers.ForEach(p >= p.ProcessUrl(""));
      var result = await Invoker.InvokeApiAsync<    SaveResponse  >(request.CreateHttpRequest(BaseUri +"/" +Version, this.invoker.DefaultHeaderMap, this.requestHandlers));
      return result;
  }

So now, PostWorkbookSaveAs() is awaitable in context. Vital for Win Forms and ASP.NET projects.

Also note that you can’t simply call .Result() on the returned Task, this also results in deadlock. So .Result() needs to be removed.

The entire call stack must be async/await.

@thomp361 We will check this issue as soon as possible