在单独线程上显示窗口只能运行一次

时间:2019-04-05 15:03:35

标签: c# wpf multithreading

我正在使用以下代码尝试在单独的线程上显示wpf窗口,以便在主窗口的UI线程填充数据的同时,它上的动画gif可以起作用:

private Thread tBusy;


private void ShowBusyWindow(string message, double top, double left, double height, double width)
{
    BusySplash busyForm = new BusySplash(message, top, left, height, width)
    busyForm.Show();
}

private void ShowBusy(string message, UIElement container)
{
    if (busy != null) return;

    double top = container.PointToScreen(new Point(0, 0)).Y;
    double left = container.PointToScreen(new Point(0, 0)).X;
    double width = container.RenderSize.Width;
    double height = container.RenderSize.Height;


    ThreadStart ts = new ThreadStart(() => ShowBusyWindow(message, top, left, height, width));
    tBusy = new Thread(ts);

    tBusy.SetApartmentState(ApartmentState.STA);
    tBusy.IsBackground = true;
    tBusy.Start();
}

private void HideBusy()
{

    tBusy.Abort();
    tBusy = null;
}

我围绕着在开始时使用ShowBusy()函数并在结尾处使用HideBusy()进行工作的代码。

但是不幸的是ShowBusy()成功运行了一次,然后抛出:

  

System.InvalidOperationException:“调用线程无法访问此对象,因为其他线程拥有它。”

我该怎么做才能防止此错误?我尝试使用busyForm的调度程序执行busyForm.Show(),但收到相同的错误。

1 个答案:

答案 0 :(得分:0)

UI工作必须卸载到UI线程上。

private void ShowBusyWindow(string message, double top, double left, double height, double width)
{
    Application.Current.Dispatcher.Invoke(() => {
        BusySplash busyForm = new BusySplash(message, top, left, height, width)
        busyForm.Show();
    });
}

不过有几件事:

  • 您确实不需要为忙碌指示器创建单独的STA线程。将非UI工作卸载到Task上,以使UI不会被阻塞。从那里开始,仅在UI线程上进行UI更新。听起来您的UI被阻止的原因是因为您在UI上做得太多。
  • 中止线程以关闭“忙碌”指示器有点奇怪。只需调用控件上的.Close(假设它是WPF窗口),这样会更加干净。