Когда ваша функция Excel работает, SynchronizationContext.Current
не установлен, поэтому механизм async / await будет запускать код после await
(включая ваш обработчик catch) в потоке ThreadPool. Это не тот контекст, в котором вы можете напрямую показать свою форму WPF.
Установка DispatcherSynchronizationContext, соответствующего Dispatcher, работающему в основном потоке (или другом потоке), будет работать, но вы должны делать это для каждого вызова UDF. Каким-то образом путь к машинному коду через Excel теряет контекст вызова .NET в основном потоке, поэтому SynchronizationContext теряется.
Лучше, вероятно, предположить, что обработчик catch работает в потоке ThreadPool, и сделать SynchronizationContext.Post
вызов из обработчика catch, чтобы вернуть вас обратно в основной поток, в котором запущены ваши Dispatcher и форма WPF.
Вы можете посмотреть, как Excel-DNA реализует окно LogDisplay (WinForms). (https://github.com/Excel-DNA/ExcelDna/blob/master/Source/ExcelDna.Integration/LogDisplay.cs). Вы можете вызвать LogDisplay.WriteLine(...)
из любого потока, и он выполнит _syncContext.Post
, чтобы запустить «Показать» в основном потоке.
Механизм async / await C # работает хуже с Excel, поскольку собственные / управляемые переходы и все, что Excel делает внутри, искажает контекст потока, который должен течь между продолжениями. Даже на стороне .NET неясно, как осуществляется управление контекстом потока между доменами приложений (разными надстройками Excel). Поэтому лучше не полагаться на то, что среда выполнения .NET может передавать любой контекст через управляемые / собственные переходы.
person
Govert
schedule
08.04.2016