|
| 1 | +AsyncAwaitMacro sample |
| 2 | +--- |
| 3 | + |
| 4 | +Shows how the ExcelAsyncUtil.QueueAsMacro mechanism can be used to implement async macros with the C# async/await mechanism. |
| 5 | + |
| 6 | +### Warning |
| 7 | + |
| 8 | +This sample does not represent 'best practice'. It just explores how the C# async/await features interact with the Excel-DNA async mechanism, and with the Excel hosting environment. |
| 9 | + |
| 10 | +Trying to run async macros as in this example will interfere with an interactive user busy with Excel: |
| 11 | + their undo stack and copy selection will get cleared at unexpected times, and any other add-ins or macros being run might be |
| 12 | + interleaved with the async code. |
| 13 | + |
| 14 | +#### `ExcelAsyncTask` |
| 15 | + |
| 16 | +The sample includes a helper class called `ExcelAsyncTask` with a single `Run` method. |
| 17 | +In turn, this starts the `Task` with a TaskScheduler which just enqueues `Task`s to run in the macro context, |
| 18 | +ensuring that the async/await continuations are again scheduled in a macro context. |
| 19 | + |
| 20 | +```c# |
| 21 | + |
| 22 | +public static void MacroToRunSlowWork() |
| 23 | +{ |
| 24 | + // Starts running SlowWork in a context where async/await will return to the macro context on the main Excel thread. |
| 25 | + ExcelTaskAsync.Run(SlowWork); |
| 26 | +} |
| 27 | + |
| 28 | +static async Task SlowWork() |
| 29 | +{ |
| 30 | + // All the code here, before and after the awaits, will run on the main thread in a macro context |
| 31 | + // (where C API calls and the COM object model is safe to access). |
| 32 | + await SomeWorkAsync(); |
| 33 | + Application.Range["A1"].Value = "abc; |
| 34 | + await OtherWorkAsync(); |
| 35 | + Application.Range["A2"].Value = "xyz; |
| 36 | +} |
| 37 | + |
| 38 | +``` |
| 39 | + |
| 40 | + |
| 41 | +#### `ExcelSynchronizationContext` |
| 42 | + |
| 43 | +The first implementation I attempted was run the async/await code in a context where `SynchronizationContext.Current` was set to an `ExcelSynchronizationContext`. |
| 44 | + |
| 45 | +There is a problem I don't yet understand when trying to use a `SynchronizationContext` in Excel-DNA. |
| 46 | +Somehow the `SynchronizationContext.Current` is cleared in the SyncWindow or macro running process. |
| 47 | +I have found references to `WindowsFormsSynchronizationContext.AutoInstall` causing trouble, but could not see how that applies in our case. |
| 48 | + |
| 49 | +It could be that the unmanaged -> managed transition interferes with the thread-based context that stores the SynchronizationContext.Current. |
| 50 | +As an alternative, we use the TaskScheduler-based approach. |
| 51 | + |
0 commit comments