Я вызываю диалог C # WPF из собственного приложения Win32 с помощью оболочки CLI.У нас есть некоторые другие диалоги, которые работают нормально, но этот демонстрирует своеобразное поведение - он также более сложный, чем другие.
Ну, с самого начала, после того, как код CLI C ++ вызывает код C #, мы устанавливаемконтекст, вызвав:
var currentContext = SynchronizationContext.Current;
if (currentContext == null && (Thread.CurrentThread.IsThreadPoolThread))
{
throw new InvalidOperationException("Can't set a dispatcher sync context on thread pool threads");
}
SynchronizationContext context = null;
// WPF needs to make sure that all GUI actions are done on the main GUI thread.
// As we are beeing called by Unmanaged C++ there is no SynchronizationContext set.
// This check make sure we will be back to the GUI thread after an await
if (currentContext == null)
{
context = new DispatcherSynchronizationContext();
if (logger != null)
{
logger.Trace(string.Format("Applying DispatcherSyncContext on thread: {0}", Thread.CurrentThread.ManagedThreadId));
}
SynchronizationContext.SetSynchronizationContext(context);
Debug.Assert(Dispatcher.FromThread(Thread.CurrentThread) != null);
}
else if (!(currentContext is DispatcherSynchronizationContext))
{
LogWarning(
"Current SynchronizationContext is not a DispatcherSynchronizationContext and may cause exceptions. Current context: " + currentContext,
logger);
context = currentContext;
}
Я не уверен, стоит ли проверять Диспетчер, а не контекст, но, насколько я знаю, это должно сработать.
Что ж, так и есть - большую часть времени.
Существует асинхронный вызов для загрузки данных из БД, который выглядит следующим образом:
public async Task<bool> AddStuff(IEnumerable<Stuff> stuffs)
{
// Материал - это poco - без логики..
CheckIfOnDispatcher(); // all well
if (!stuffs.Any())
{
return false;
}
var failureText = await Task.Run(() =>
{
return GetStuffDetails(DataService, stuffs);
}).ConfigureAwait(true);
CheckIfOnDispatcher(); // here its not on dispatcher anymore
Был добавлен метод Check для отладки происходящего:
[Conditional("DEBUG")]
void CheckIfOnDispatcher()
{
if (Dispatcher.FromThread(Thread.CurrentThread) == null)
{
UserFeedback.ShowFeedback($"Not on GUI: {Thread.CurrentThread.ManagedThreadId}");
}
}
После await Task.Run, только иногда, он не вернется в основной поток, но продолжитна рабочем потоке.
Такое поведение действительно происходит только на клиенте win32, если мы вызываем его из клиента Windows Form или C # WPF, проблем нет.Похоже, что основной поток из приложения win32 MFC имеет какое-то особое поведение, но я не могу найти какую-либо документацию по этому поводу.
Неправильно ли мы устанавливаем контекст?Я также пытался открыть диалоговое окно, свернутое с самого начала, и скрыть его снова, но это также не сработало (вместо настройки контекста)
PS: UserFeedback вызывает MessageBox, который также работает безДиспетчер ...
TIA,
Марко