ExcelAsyncUtil.Run() and Re-Calling UDF

52 views
Skip to first unread message

Anthony LaPaso

unread,
Oct 21, 2021, 3:55:39 PM10/21/21
to Excel-DNA
Hello everyone,

I am doing some testing with ExcelAsyncUtil.Run() and I am finding that when some UDF, A(), calls a second method, B(), and B() then calls ExcelAsyncUtil.Run(), eventually A() is called again in what seems to be some kind of "call back" when the delegate initiated in B() finishes execution.

Here's an example of my UDF A():

[ExcelFunction(Name ="sleeper")]
public static object sleeper(
[ExcelArgument(Name = "sleeper")] int millis)
{
   Debug.WriteLine($"Entering UDF...current Thread Id and name: {Thread.CurrentThread.ManagedThreadId}, \"{Thread.CurrentThread.Name}\"");
   Object obj = udf_SLEEP(millis);

   Debug.WriteLine("UDF got back a type of " + obj.GetType());

   Debug.WriteLine("Leaving UDF...");
   return obj;
}


Now here is the second method, B():

private static object udf_SLEEP(int sOneArgument)
{
   return ExcelAsyncUtil.Run("Async1", sOneArgument, () =>
   {
      int millis = Convert.ToInt32(sOneArgument);

      Debug.Print($"Begin Sleep: {DateTime.Now:HH:mm:ss.fff} Sleeping for {millis} ms, current Thread Id and name: { Thread.CurrentThread.ManagedThreadId}, \"{ Thread.CurrentThread.Name}\"");
      Thread.Sleep(millis);

      Debug.Print($"End Sleep:   {DateTime.Now:HH:mm:ss.fff} Sleeping for {millis} ms, current Thread Id and name: { Thread.CurrentThread.ManagedThreadId}, \"{ Thread.CurrentThread.Name}\"");
   return "Woke Up at " + DateTime.Now.ToString("1:HH:mm:ss.fff");
   });
}

Here is the output when I call sleeper(5000)
Entering UDF...current Thread Id and name: 1, ""
UDF got back a type of ExcelDna.Integration.ExcelError
Leaving UDF...
Begin Sleep: 14:19:00.463 Sleeping for 5000 ms, current Thread Id and name: 4, ""
End Sleep:   14:19:05.474 Sleeping for 5000 ms, current Thread Id and name: 4, ""
Entering UDF...current Thread Id and name: 1, ""
UDF got back a type of System.String
Leaving UDF...


You see what's happening: the sleeper() method is being called twice -- once when the user presses Enter and again when the delegate completes execution. The udf_SLEEP() method is called twice as well, but the delegate only runs once. The first time udf_SLEEP() is called it returns an ExcelDna.Integration.ExcelError whereas the second time it returns the string from the delegate.

Can someone (whose first name might begin with a "G") offer some explanation of how this happens? We are in the process of converting all the "B()" methods into regular async methods, removing the need to call ExcelAsynUtil.Run(), but we want to understand the mechanism. We are also debugging some of the methods that are not working right and we need an understanding of what's going on. 

Specifically, how is it that the sleeper() method is somehow automatically re-called?

Thanks very much.

Reply all
Reply to author
Forward
0 new messages