/ / Dispatcher.Inkoke блокове завинаги - WPF, извикване, диспечер

Dispatcher.Invoke блокира завинаги - wpf, invoke, dispatcher

Опитвам се да извикам диалогов прозорец в диспечера на потребителския интерфейс:

class DialogService : IDialogService
{
private readonly Dispatcher _dispatcher = Application.Current.Dispatcher;

public bool? Show(IDialogViewModel viewModel)
{
if (_dispatcher.CheckAccess())
{
var dialogWindow = new DialogWindow();
return dialogWindow.Show(viewModel);
}
else
{
Func<IDialogViewModel, bool?> func = Show;
return (bool?)_dispatcher.Invoke(func, viewModel);
}
}
}

Въпреки това повикването до Invoke блокира завинаги, и Show никога не се извиква в нишката на потребителския интерфейс ...

Използвайки BeginInvoke не е опция: Нуждая се от резултата веднага, защото обработвам събитие от отдалечен обект (използвайки.

Някаква идея ?


UPDATE

Ето по-пълно описание на проблема:

Имам клиентско приложение, което комуникирас услуга на Windows, използваща .NET Remoting. В някакъв момент клиентът се обажда на услугата, за да извърши операция (това повикване се задейства от потребителско действие, кликване върху бутон в този случай). Услугата може да се нуждае от идентификационни данни за извършване на операцията: в този случай тя повдига a CredentialsNeeded събитие, обработвано от клиента. След това клиентът показва диалогов прозорец, който подсказва на потребителя за идентификационни данни, и задава подходящите свойства в аргументите на събитието.

Така че, когато получа събитието, нишката на потребителския интерфейс изчаква операция да бъде завършена от страната на услугата ... Предполагам, че е причината Invoke обаждането не се обработва, но как мога да го заобиколя? Мога ли да създам още UI thread, за да покаже диалоговия прозорец? В WinForms, знам, че мога да стартирам друго помпено съобщение с Application.Run, но аз не знам как да направя същото в WPF ...

Отговори:

4 за отговор № 1

Притежавате ли заключване по време на този метод, който се опитва да придобие друг метод в нишката на потребителския интерфейс? Това със сигурност щеше да го обясни.

Дали това се случва всеки път? Това очевидно би улеснило диагностицирането.

Необичайно за мен бих предложил да отида на дебъгера: просто натиснете удар и вижте какво правят темите.

И накрая, знам, че имате нужда от резултата ... но какво ще стане, ако вие правя обадете се BeginInvoke вместо това (и да върнете фиктивна стойност)? Дали това се позовава на метода в диспечера или не? Очевидно това няма да бъде дългосрочно решение, но ще даде повече диагностична информация.


1 за отговор № 2

Дали нишката на потребителския интерфейс да блокира повикването къмнещо друго (може би вашата основна нишка) в момента, в който се опитвате да използвате Invoke? Ако е така, тогава имате класическа задънена улица на ръцете си. Две нишки, които чакат другия да се върне.

В Windows Forms правят много задсцени "изпомпване на съобщения" често, когато най-малко го очакват в усилието да се избегне мъртвата точка, но много пъти създава още повече проблеми и е трудно да се намерят бъгове поради неочаквана повторна врата.

Ако не мислите, че темата на потребителския интерфейс е вПроцесът на блокиране на повикването, трябва да стартирате приложението в дебъгера и да прекъсне дебъгера, когато се появи застой. След това погледнете в прозореца Threads на основната нишка. Щракнете два пъти върху главната нишка, след което погледнете прозореца на стека за повиквания, за да видите къде седи основната нишка.

Можете също да опитате изрично да посочите DispatcherPriority of Send, въпреки че не мисля, че това ще има значение, ако има истинска безизходица.


1 за отговор № 3

В крайна сметка открих решение на проблема си: просто трябва да покажа диалоговия прозорец на нова нишка със собствен диспечер. Ето променения код:

class DialogService : IDialogService
{
private readonly Dispatcher _dispatcher = Application.Current.Dispatcher;

public bool? Show(IDialogViewModel viewModel)
{
if (_dispatcher.CheckAccess())
{
DoShow(viewModel);
}
else
{
bool? r = null;
Thread thread = new Thread(() => r = DoShow(viewModel));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
return r;
}
}

private static bool? DoShow(IDialogViewModel viewModel)
{
var dialogWindow = new DialogWindow();
return dialogWindow.Show(viewModel);
}
}