これを処理するためにスレッドを起動する必要があるというIMOの回答は、誤った方向に進んでいます。必要なのは、ウィンドウをメインのディスパッチャスレッドにジャンプして戻すことです。
WPFで
public ShellViewModel(
[NotNull] IWindowManager windows,
[NotNull] IWindsorContainer container)
{
if (windows == null) throw new ArgumentNullException("windows");
if (container == null) throw new ArgumentNullException("container");
_windows = windows;
_container = container;
UIDispatcher = Dispatcher.CurrentDispatcher; // not for WinForms
}
public Dispatcher UIDispatcher { get; private set; }
次に、別のスレッド(この場合はスレッドプールスレッド)で何らかのイベントが発生した場合:
public void Consume(ImageFound message)
{
var model = _container.Resolve<ChoiceViewModel>();
model.ForImage(message);
UIDispatcher.BeginInvoke(new Action(() => _windows.ShowWindow(model)));
}
WinFormsと同等
UIDispatcherを何にも設定しないでください。そうすれば、次のことができます。
public void Consume(ImageFound message)
{
var model = _container.Resolve<ChoiceViewModel>();
model.ForImage(message);
this.Invoke( () => _windows.ShowWindow(model) );
}
WPF用に乾燥させる:
男、たくさんのコード...
public interface ThreadedViewModel
: IConsumer
{
/// <summary>
/// Gets the UI-thread dispatcher
/// </summary>
Dispatcher UIDispatcher { get; }
}
public static class ThreadedViewModelEx
{
public static void BeginInvoke([NotNull] this ThreadedViewModel viewModel, [NotNull] Action action)
{
if (viewModel == null) throw new ArgumentNullException("viewModel");
if (action == null) throw new ArgumentNullException("action");
if (viewModel.UIDispatcher.CheckAccess()) action();
else viewModel.UIDispatcher.BeginInvoke(action);
}
}
ビューモデルでは:
public void Consume(ImageFound message)
{
var model = _container.Resolve<ChoiceViewModel>();
model.ForImage(message);
this.BeginInvoke(() => _windows.ShowWindow(model));
}
それが役に立てば幸い。