This project has moved. For the latest updates, please go here.


ExcelAsyncUtil.QueueAsMacro in subsequent tasks causes hang


I have a situation encountered with my company's excel add-in. We're currently using a WinForms timer to ostensibly schedule tasks to run on the main excel thread. I don't trust it, and we (rarely) get COMExceptions indicating that things aren't behaving well. We shouldn't need the timer, but we need to reread certain info from a sheet any time the active sheet has changed (there are events for this), or we've made a change. It seems to me that the timer we have in place is unnecessary, and may even be the cause for a number of our COM exceptions, so I'm trying to read it and move all of our read/writes of worksheet based data to the Excel Main thread. Since these are .Net originated events, obviously these somehow need to be dispatched to the main Excel thread. I found the ExcelDna.ExcelAsyncUtil.QueueAsMacro function, which mostly fulfills my need, but, if a queued function in turn queues another function, I'm seeing that the second call hangs, with no indication as to why. I am able to queue multiple functions, so long as none of them directly cause another function to be queue. I suspect that the dequeue method holds a write-lock on the queue for too long. Whether by design or accident, I'm not sure.

It feels to me that the locking structure around queued functions is not quite correct. It seems that if a queued function is called, a chained function that needs to be invoke cannot be queued. Doing so results in a hang after the first call completes, but before the second has had a chance to execute. Unfortunately, I've not been able to get a good stack of non-add-in functions, even using a custom built debug version of ExcelDNA.Integration.
Closed Sep 30, 2015 at 10:33 PM by govert
Can't reproduce


govert wrote Jun 17, 2015 at 11:04 AM

I'd be very interested in checking this further.

Could you please move this issue to GitHub:
and make a small .dna file or simple source file that I can build with the NuGet package, in order to reproduce?


govert wrote Jun 17, 2015 at 10:50 PM

I did have a quick look at the locking code around the macro queue, and the code that runs your delegate or macro is not inside the lock - only the queue manipulation itself is guarded. So a first quick look didn't show the problem. I've not tried to build a sample that would test it, though. Help with that would be appreciated.


govert wrote Jun 21, 2015 at 12:38 PM

OK - I've made a test a can't recreate the problem you report. I run the following function:
public static object StartNestedAsync()
            ExcelAsyncUtil.QueueAsMacro(() =>
                    dynamic app = ExcelDnaUtil.Application;
                    app.Range["B5"].Value = "Async setter before nested call";
                    ExcelAsyncUtil.QueueAsMacro(() =>
                            dynamic appInside = ExcelDnaUtil.Application;
                            app.Range["B6"].Value = "Async setter inside nested call";
                    app.Range["B7"].Value = "Async setter after nested call";

            return "Started...";
Everything works as expected.

Please let me know if you are able to reproduce the issue you report.