Dispatcher.Invoke висит в WordAddin

Я написал WordAddIn, который позволяет пользователю вызывать некоторые метаданные для текущего документа. Через пользовательскую кнопку на ленте они могут вызывать WPF. Вызов WPF реализован следующим образом:

        System.Windows.Application app = null;

а затем в методе, вызываемом кнопкой:

if (app == null)
{
    app = new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown };
    app.Run();
}
MainWindow win = new MainWindow(graph);
app.Dispatcher.Invoke((Action)(() => { win.Show(); }));

При первом нажатии кнопки после запуска Word ничего не происходит, и редактирование содержимого в документе Word становится невозможным. При повторном нажатии кнопки объект WPF загружается и отображается, это также работает для любого нажатия кнопки впоследствии. Так что кажется при первом вызове диспетчер зависает. Как мне это предотвратить?

2 ответа

Решение

Я получил помощь с этим на форумах Microsoft WPF. Создание и вызов приложения в новом потоке делает свое дело, так как приложение действительно блокирует текущий поток, в котором оно вызывается.

                    if (app == null)
                    {
                        Thread thread = new Thread(new ThreadStart(() =>
                            {
                                app = new System.Windows.Application { ShutdownMode = ShutdownMode.OnExplicitShutdown };
                                autoResetEvent.Set();
                                app.Run();
                            }));
                        thread.SetApartmentState(ApartmentState.STA);
                        thread.Start();
                    }
                    else 
                    {
                        autoResetEvent.Set();
                    }
                    autoResetEvent.WaitOne(); //wait until app has been initialized on the other thread
                    app.Dispatcher.Invoke((Action)(() => { new MainWindow(graph).Show(); }));                       
                    }

Я не уверен, почему вы хотите отправить вызов в любом случае, так как это тот же поток. Вам необходимо маршалировать вызовы потока UI только в том случае, если "текущий" поток не является потоком UI, что не относится к вашему случаю - у вас есть только один поток.

Во-вторых, Application.Run является методом блокировки и не должен вызываться в контексте надстройки. Вы не можете создать приложение WPF внутри приложения Add-In. Кстати, Application.Run всегда запускается в текущем потоке, который в вашем случае является тем же, в котором работает надстройка Word. И так оно и должно быть.

Если я вас правильно понимаю, вы создаете приложение WPF, потому что вы не хотите использовать технологию WinForms, а WPF. Сделайте это без Application.Run и не отправляйте вызовы, потому что для этого нет причин.

Другие вопросы по тегам