【问题标题】:Starting a WPF window from a class library project从类库项目启动 WPF 窗口
【发布时间】:2011-04-08 11:26:20
【问题描述】:

我正在创建一种“加载屏幕”,它将在一些繁重的处理之前从类库中显示,然后在处理完成时隐藏。我的问题是,无论我做什么,繁重的处理似乎都阻塞了 UI 线程。我必须使用[STAThread] 属性设置方法,以便实际创建窗口。然后我使用以下方法显示窗口:

bw = new BusyWindow();
bw.Show();

然后在处理完成后用bw.Hide() 隐藏它。我已经为处理创建了一个任务,所以它应该在一个单独的线程上运行..?当然,除非 STAThread 完全搞砸了?

更多代码:

var taskStart = Task.Factory.StartNew(() => ShowBusyWindow());
var taskProcess = taskStart.ContinueWith((antecedent) => GetInternal());
var taskEnd = taskProcess.ContinueWith((antecedent) => HideBusyWindow());

return taskProcess.Result;

和 ShowBusywindow

public void ShowBusyWindow()
        {
            bw = new BusyWindow();
            bw.Show();
        }

还有 HideBusyWindow:

public void HideBusyWindow()
        {
            bw.Close();
        }

我还应该提到我正在尝试将这个库公开给 COM,因此它可以从一些 VB6 代码运行。我不知道这是否对任何事情有影响...?

【问题讨论】:

  • 请提供更多代码,特别是您创建任务并开始处理的部分。
  • 我添加了更多信息
  • 我想指出,让类库创建自己的 UI 元素可能很危险。让类库在开始“繁重处理”之前发出某种通知可能是一个更好的主意,这样无论使用该库的客户端都可以决定是否显示“加载”屏幕。
  • 好的。不过,我非常希望这个加载屏幕出现在 WPF 中,有没有办法做到这一点......?

标签: c# wpf


【解决方案1】:

好的,因此可以使用以下方法从类库或任何其他线程中调用 WPF 窗口:

thread = new Thread(() =>
        {
            bw = new BusyWindow();
            bw.Show();
            bw.Closed += (s, e) => bw.Dispatcher.InvokeShutdown(); 
            Dispatcher.Run();
        });
        thread.SetApartmentState(ApartmentState.STA);
        //thread.IsBackground = true;
        thread.Start();

您实际上并不需要 IsBackground。唯一需要的是当窗口关闭时线程 Dispatcher 没有关闭。如果不关闭它会创建一个“幽灵线程”。

显然必须将公寓状态设置为 STA,这样才能真正创建窗口。根据this 网站,单线程 WPF 窗口对于 UI 密集型窗口(大量图形等)非常有用。

要关闭窗口,我只需调用thread.Abort()。我认为这不是最干净的方法,但它可以满足我的需要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    相关资源
    最近更新 更多