我可以回到线程执行上下文吗?

3
我需要在另一个线程上创建一个表单,就像应用程序启动时的闪屏界面一样。
LoadingMyForm w = null;
Thread thread = new Thread(() =>
{
    try
    {
        w = new LoadingMyForm();
        w.Show();

        System.Windows.Threading.Dispatcher.Run();
    }
    catch (Exception ex)
    {
        w.Close();
        w = null;
    }
});

thread.SetApartmentState(ApartmentState.STA);
thread.Start();

这个方法现在可以使用,但是要停止它,我必须调用thread.Abort();,这将引发一个异常,当我捕获到该异常时,正如你所看到的,我关闭了窗口。是否有一种机制可以回到线程执行上下文并仅调用表单上的Close方法呢?
据我理解:
System.Windows.Threading.Dispatcher.Run();

保持我的线程活跃,那么,是否可能将其他操作分配给在此线程上运行?

2个回答

2

只需使用表单的Dispatcher来完成工作。最简单的调用方法是这样的:

w.Dispatcher.Invoke(w.Close);

虽然你可能想要给LoadingMyForm类添加一个方法来包装这个逻辑:

public void ThreadSafeClose()
{
    Dispatcher.Invoke(Close);
}

请注意,虽然这样可以安全地关闭窗口,但是它将使ThreadDispatcher仍在运行 - 您可能需要手动关闭它们,但从您的问题中看来,您希望稍后重复使用线程。同样,Dispatcher.InvokeDispatcher.BeginInvoke方法将对您有所帮助。


1
以下是另一种做法。用法如下:
var splash = new SplashWindow();

// continue when the window is shown
splash.Start(() => new LoadingMyForm());

// do some initialization work
// ...

splash.Stop();

实现:

class SplashWindow
{
    CancellationTokenSource _cts;
    Thread _thread;

    // show window
    public void Start(Func<Window> createWindow)
    {
        var tcs = new TaskCompletionSource<bool>(false);
        _cts = new CancellationTokenSource();
        var token = _cts.Token;

        _thread = new Thread(() =>
        {
            var window = createWindow();
            window.Loaded += (s, e) =>
            {
                // window is shown
                tcs.SetResult(true);
            };

            var dispather = Dispatcher.CurrentDispatcher;
            dispather.InvokeAsync(() =>
                window.Show());

            using (token.Register(() =>
                dispather.BeginInvokeShutdown(DispatcherPriority.Normal),
                useSynchronizationContext: false))
            {
                Dispatcher.Run();
            }

            window.Close();
        });

        _thread.IsBackground = true;
        _thread.SetApartmentState(ApartmentState.STA);
        _thread.Start();
        tcs.Task.Wait();
    }

    // hide window
    public void Stop()
    {
        _cts.Cancel();
        _thread.Join();
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接