Excel/Addin hanging when using GetAwaiter.GetResult downstream of an ExcelAsyncFunction

123 views
Skip to first unread message

Graeme Smith

unread,
Mar 12, 2024, 8:27:54 AM3/12/24
to Excel-DNA
Hi

We recently ported the majority of our functions to use the ExcelAsyncFunction attribute, which gives us far superior performance and user experience.

There is one edge case, however:

If we have an ExcelAsyncFunction (or synchronous ExcelFunction) which has, downstream somewhere, a call which does GetAwaiter().GetResult(), then Excel hangs for a few minutes, before returning the "Microsoft Excel is waiting for another application to complete an OLE action" popup. 

On clicking "Cancel", the exception is
System.Runtime.InteropServices.COMException (0x80004005): Unspecified error (0x80004005 (E_FAIL))
   at System.Threading.Monitor.ObjWait(Int32 millisecondsTimeout, Object obj)
   at System.Threading.Monitor.Wait(Object obj, Int32 millisecondsTimeout)
   at System.Threading.ManualResetEventSlim.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.SpinThenBlockingWait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at System.Threading.Tasks.Task.InternalWaitCore(Int32 millisecondsTimeout, CancellationToken cancellationToken)
   at *.*.ProofOfHang()

Code to reproduce:
[ExcelAsyncFunction]
public static async Task<string> ProofOfHang()
{
AsyncTask().GetAwaiter().GetResult();

return "bob";
}

internal static async Task AsyncTask()
{
await Task.Delay(5000);
}

[ExcelFunction]
public static string ProofOfHang2()
{
AsyncTask().GetAwaiter().GetResult();

return "bob";
}
Both ProofOfHang and ProofOfHang2 "hang".

We register our async functions at addin load:
ExcelRegistration
.GetExcelFunctions()
.ProcessAsyncRegistrations(nativeAsyncIfAvailable: false)


In our case, we cannot, at this stage, untangle the downstream code to provide a "pure" async path.

We are using v1.7.0

Thanks
Graeme

Govert van Drimmelen

unread,
Mar 13, 2024, 6:09:22 AM3/13/24
to exce...@googlegroups.com

Hi Graeme,

 

Could you give this a try:

 

        [ExcelAsyncFunction]

        public static string NotHanging()

        {

            AsyncTask().GetAwaiter().GetResult();

 

            return "bob";

        }

 

        [ExcelAsyncFunction]

        public static string NotHanging2()

        {

            System.Threading.Thread.Sleep(5000);

            return "bob";

        }

 

A function that does not return Task<T> but is marked with [ExcelAsyncFunction] will be wrapped inside a Task.Run( …).

Your other options run synchronously until the Task itself is returned, and since you are calling GetResult() will block.

 

-Govert

--
You received this message because you are subscribed to the Google Groups "Excel-DNA" group.
To unsubscribe from this group and stop receiving emails from it, send an email to exceldna+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/exceldna/177191a4-23f7-4034-bea1-76566559e047n%40googlegroups.com.

Graeme Smith

unread,
Mar 13, 2024, 7:54:06 AM3/13/24
to Excel-DNA
Thanks Govert!

Changing all the impacted method signatures from 
static async Task<T> Method()
to 
static T Method()

whilst retaining the ExcelAsyncFunction attribute solves the issue.
Reply all
Reply to author
Forward
0 new messages