在另一个线程

时间:2016-11-07 19:40:22

标签: wpf multithreading console

所以我正在开发一个控制台项目,它应该在某个时刻显示一个WPF窗口,在这个窗口中我可以看到图形的可视化表示,同时继续运行算法。

我到目前为止我可以创建一个Window并在另一个线程中打开它,但是一旦我调用Dispatcher.Run(),控制台就会被阻止。到目前为止我的方法:

第1步:创建一个线程,一旦运行就为自己创建ApplicationSynchronizationContext

第2步:使用sync-context调用应用程序的方法(它是提供这些方法的继承自定义类),使用传输类创建窗口的线程。 期望:它应该创建一个由独立UI线程拥有的Window实例。

第3步:使用线程的sync-context调用应用程序上的ShowWindow()方法,该方法显示Window(确实有效),然后运行Dispatcher。因为它是使用线程的sync-context调度的,所以它不应该锁定Console线程。 确实如此

第4步:使用Window的调度程序调用图表的更新方法。

好吧,在我的想法中,这应该非常好用,但Dispatcher以某种方式锁定了Console线程,而不是UI线程。我在这里忽略了什么吗?

自定义应用

internal sealed class CrossThreadApplication : Application
{
    private SynchronizationContext _context;

    ///=================================================================================================
    /// <summary>   Constructor. </summary>
    ///
    /// <param name="context">  The context. </param>
    ///=================================================================================================
    public CrossThreadApplication(SynchronizationContext context)
    {
        if (context == null) throw new ArgumentNullException(nameof(context));
        _context = context;
    }

    ///=================================================================================================
    /// <summary>   Shows the window. </summary>
    ///
    /// <exception cref="ArgumentNullException">    Thrown when one or more required arguments are
    ///                                             null. </exception>
    ///
    /// <param name="window">   The window. </param>
    ///=================================================================================================
    public void ShowWindow(Window window)
    {
        if (window == null) throw new ArgumentNullException(nameof(window));
        _context.Send(state =>
        {
            ((Window)state).Show();
            System.Windows.Threading.Dispatcher.Run();
        }, window);
    }

    ///=================================================================================================
    /// <summary>   Creates a new object. </summary>
    ///
    /// <param name="handle">   The creation handle for a Window. </param>
    ///
    /// <returns>   An object. </returns>
    ///=================================================================================================
    public void Create(CreationHandle<Window> handle)
    {
        _context.Send(state =>
        {
            CreationHandle<Window> hnd = (CreationHandle<Window>) state;
            hnd.Set(Activator.CreateInstance(hnd.CreationType));
        }, handle);
    }
}

承载UI线程并与应用程序交互的UIHost类

static UIHost()
{
    HostThread = new Thread(Start);
    HostThread.SetApartmentState(ApartmentState.STA);
    HostThread.Name = "UI Thread";
    CreationEvent = new ManualResetEvent(false);
    HostThread.Start(CreationEvent);
}

private static void Start(object o)
{
    ManualResetEvent ev = (ManualResetEvent) o;

    SynchronizationContext context = new SynchronizationContext();
    SynchronizationContext.SetSynchronizationContext(context);

    _application = new CrossThreadApplication(context);
    ev.Set();
    _application.Run();
}

///=================================================================================================
/// <summary>   Executes the user interface operation. </summary>
///
/// <param name="windowType">   The window type. </param>
/// <param name="reset">        The reset. </param>
///
/// <returns>   An object. </returns>
///=================================================================================================
internal static object RunUI(Type windowType, ManualResetEvent reset)
{
    CreationEvent.WaitOne();
    CreationHandle<Window> handle = new CreationHandle<Window>();
    _application.Create(handle);
    _application.ShowWindow(handle.Get());
    reset.Set();
    return handle.Get();
}

问题出现在CrossThreadApplication.ShowWindow() *.Dispatcher.Run();

为什么会这样?我怎样才能使这个工作?它必须以某种方式。

0 个答案:

没有答案