1

Closed

ExcelAsyncUtil.QueueAsMacro in subsequent tasks causes hang

description

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 9:33 PM by govert
Can't reproduce

comments

govert wrote Jun 17, 2015 at 10:04 AM

I'd be very interested in checking this further.

Could you please move this issue to GitHub: https://github.com/Excel-DNA/ExcelDna/issues
and make a small .dna file or simple source file that I can build with the NuGet package, in order to reproduce?

-Govert

govert wrote Jun 17, 2015 at 9: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

govert wrote Jun 21, 2015 at 11:38 AM

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.

-Govert