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 и не отправляйте вызовы, потому что для этого нет причин.