gpt4 book ai didi

c# - 如何要求 GUI 线程创建对象?

转载 作者:太空宇宙 更新时间:2023-11-03 15:38:45 24 4
gpt4 key购买 nike

我的 Windows 窗体应用程序中有以下程序流(不幸的是,WPF 不是一个可行的选项):

  1. GUI 线程创建一个初始屏幕和一个非常空的主窗口,两者都继承了 Form
  2. 启动画面显示并提供给 Application.Run()
  3. 初始屏幕将发送一个事件,该事件触发一个执行初始化的 async 事件处理程序,使用 IProgress 接口(interface)向 GUI 报告进度。 (这完美无缺。)​​
  4. 在初始化过程中的某个时候,我需要根据某些插件提供的信息动态创建 GUI 组件并将它们添加到主窗口。

此时我卡住了:我知道我需要让 GUI 线程为我创建这些组件,但是没有 Control 我可以调用 InvokeRequired在。执行 MainWindow.InvokeRequired 都不起作用。

我能想到的唯一想法是触发一个连接到 GUI 线程中的工厂的事件,然后等待该工厂触发另一个提供已创建控件的事件。但是我很确定有一个更强大的解决方案。有谁知道如何实现这一点?

最佳答案

使用对我的问题的评论,尤其是关于让我找到 this very useful question 的延续方法的注释,我实现了以下目标:

  • 初始化的第一部分是异步执行的(没有变化)。
  • 初始化的第二部分(创建 UI 元素)随后作为延续任务在 UI 线程的上下文中执行。
  • 除了相当短的 GUI 初始化部分外,初始屏幕是响应式的(即鼠标光标悬停在初始屏幕上后不会变为“等待”)。
  • 两个初始化例程都不知道启动画面(也就是说,我可以很容易地交换它)。
  • 核心 Controller 只知道SplashScreen界面,甚至不知道它是一个Control
  • 目前没有异常处理。这是我的下一个任务,但不影响这个问题。

TL;DR:代码看起来有点像这样:

public void Start(ISplashScreen splashScreen, ...)
{
InitializationResult initializationResult = null;
var progress = new Progress<int>((steps) => splashScreen.IncrementProgress(steps));
splashScreen.Started += async (sender, args) => await Task.Factory.StartNew(

// Perform non-GUI initialization - The GUI thread will be responsive in the meantime.
() => Initialize(..., progress, out initializationResult)

).ContinueWith(

// Perform GUI initialization afterwards in the UI context
(task) =>
{
InitializeGUI(initializationResult, progress);
splashScreen.CloseSplash();
},
TaskScheduler.FromCurrentSynchronizationContext()

);

splashScreen.Finished += (sender, args) => RunApplication(initializationResult);

splashScreen.SetProgressRange(0, initializationSteps);
splashScreen.ShowSplash();

Application.Run();
}

关于c# - 如何要求 GUI 线程创建对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30916002/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com