【问题标题】:WPF Access window created on different UI thread在不同的 UI 线程上创建的 WPF 访问窗口
【发布时间】:2019-05-06 19:36:04
【问题描述】:

我在不同的线程上创建了新窗口,因为它有繁重的 UI 操作,这样做是为了让我的主窗口顺利运行。一切都很完美。

但这里有个问题:
如何访问新创建的窗口?
致电Dispatcher.Run() 后,我无法再操纵visualisationWindow。我想继续访问那个新创建的窗口对象。

这是我的窗口的创建方式:

    private void CreateVisualisationWindow()
    {
        Thread VisualisationWIndowThread = new Thread(new ThreadStart(ThreadStartingPoint));
        VisualisationWIndowThread.SetApartmentState(ApartmentState.STA);
        VisualisationWIndowThread.IsBackground = true;
        VisualisationWIndowThread.Start();
    }

    private void ThreadStartingPoint()
    {
        Visualisation visualisationWindow = new Visualisation();
        visualisationWindow.Show();
        System.Windows.Threading.Dispatcher.Run();
    }

我也尝试通过System.Windows.Threading.Dispatcher.FromThread(VisualisationWIndowThread) 访问它,但似乎我误解了一些核心内容。

【问题讨论】:

  • 使用多个 ui 线程是您在技术上可以做的事情之一,但几乎总是一个坏主意。我认为使用一个 ui 线程的不同方法可能是一个更好的计划。您的可视化窗口实际上是做什么的?作为替代方案,为什么需要访问实际窗口?我希望使用某种与 UI 无关的视图模型,它可以处理多个线程。
  • @Andy,只有多个 ui 线程,因为第二个窗口包含大量使用 UI 线程的 WinForms 元素(screenBG.Render() 其中 screenBG 是 BufferedGraphics 类型 - 该方法只能在 UI 线程上执行) 并且即使使用异步方法也无法避免它。用于展示一些科学数据
  • 我不熟悉screenbg.render。你必须用那个吗?我在想也许是 writeablebitmap。在后台线程上处理,转换为位图,冻结并传回。虽然....只是构建一个 wbm 非常快,只要您在更改之间释放一点 ui 线程,您就可以构建非常快速变化的图像。

标签: c# wpf multithreading


【解决方案1】:

我使用两个 WPF Window 对象和一个计时器模拟了您的问题,以确保在对其调用操作之前创建第二个窗口。下面是我的代码示例,它每五秒更新第二个 Windows 文本框:

    private Timer _timer;
    private SecondWindow _secondWindow;

    public MainWindow()
    {
        InitializeComponent();
        CreateVisualisationWindow();
        _timer = new Timer(Callback);
        _timer.Change(5000, 5000);
    }

    private void Callback(object state)
    {
        UpdateSecondWindowText();
    }

    private void CreateVisualisationWindow()
    {
        Thread VisualisationWIndowThread = new Thread(ThreadStartingPoint);
        VisualisationWIndowThread.SetApartmentState(ApartmentState.STA);
        VisualisationWIndowThread.IsBackground = true;
        VisualisationWIndowThread.Start();
    }

    private void ThreadStartingPoint()
    {
        _secondWindow = new SecondWindow();
        _secondWindow.SecondWindowTextBlock.Text = "Hello";
        _secondWindow.Show();
         Dispatcher.Run();
    }

    private void UpdateSecondWindowText()
    {
        _secondWindow.Dispatcher.BeginInvoke(new Action(() =>
        {
            _secondWindow.SecondWindowTextBlock.Text = _secondWindow.SecondWindowTextBlock.Text + " World";
        }));
    }

所以诀窍是,您需要在第二个窗口上调用 Dispatcher 才能访问它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 2012-04-22
    • 2023-03-28
    • 2013-08-19
    • 1970-01-01
    • 2020-10-21
    相关资源
    最近更新 更多