gpt4 book ai didi

C# - 跨线程操作 - 在线程中创建控件,添加到主窗体

转载 作者:行者123 更新时间:2023-11-30 22:34:36 25 4
gpt4 key购买 nike

我有一个旧的表单,此时我真的不想重写,所以我正在做的是加载表单,然后将它添加到新 UI 表单的面板中。这工作正常,但速度很慢。旧的表单会加载和收集大量数据,而且效率不高。因此,较大的记录加载最多需要 30 秒。如您所知,创建表单然后在加载旧表单时“锁定”主 UI 大约 30 秒。这是我试图阻止的行为。我想加载新表单,在空白面板中显示“正在加载”gif,然后在加载旧表单后删除“正在加载”图像并将表单添加为控件。

问题就在这里开始了。

我已经尝试创建一个后台 worker ,但这会导致 STA 错误(旧形式有一些它自己的线程数据加载),并且由于我无法将 worker 更改为 STA,所以我停止了尝试。

我已经尝试创建一个 Invoke(和 BeginInvoke),虽然这有效,但它并没有真正在线程中加载旧表单。它只是将它发送回 UI 线程并在那里完成工作。这再次挂起 UI。 I.E.:不是我想要的。

我尝试创建一个委托(delegate)并将其作为线程中的事件触发,但我得到的结果与下面相同...

我创建了一个线程,在其上设置了 STA,启动了它,然后执行了一个 while 循环,其中有一个 DoEvents 等待它完成。当然,这一切似乎都可以正常工作,直到将表单添加到面板,然后我得到“控制‘ChartForm’从创建它的线程以外的线程访问”。在此错误中,“ChartForm”是线程中加载的旧图表。

我已经尝试过上述方法,但我使用了一个私有(private)静态字段来保存旧表单的创建,然后在线程完成后将其添加到面板。这是在创建线程的方法中,就在 while 循环之后。同样的错误。

因此,我在其他地方对 DataTables 使用了上述方法,并且在将数据返回主线程以与 DataBinding 一起使用时没有任何问题。我知道这有点不同,但我没想到会这么难。

下面是我尝试使用的代码,它似乎最接近我想要的。

private static _ChartForm;
private void LoadPatientChart()
{
ClearMainPanel(); // Removes any loaded ChartForms from Panel
if (_Patient == null) // Test to make sure a patient is loaded
return;

loadingPanel.Visible = true; // Displays the "Loading" gif

Thread thread = new Thread(new ThreadStart(this.GetChartForm));
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
while (thread.ThreadState != ThreadState.Stopped)
Application.DoEvents(); // Keeps the UI active and waits for the form to load

this.ChartPanel.Controls.Add(_ChartForm); // This is where the error is
loadingPanel.Visible = false; // Hide the "Loading" gif

}

private void GetChartForm()
{
ChartForm chartForm = new ChartForm(_Patient.AcctNum.ToString(), false);
chartForm.TopLevel = false;
chartForm.FormBorderStyle = FormBorderStyle.None;
chartForm.Dock = DockStyle.Fill;
chartForm.Visible = true;
_ChartForm = chartForm;
}

最佳答案

在 UI 线程以外的任何其他线程上创建 UI 控件确实不是一个好主意。这在技术上是可行的,但很难管理,尤其是当新线程是“临时”线程时。

您真正需要做的是重构 ChartForm 正在执行的工作(在构建时它出现了吗?)并在后台线程上执行该工作,然后将其返回到您的 UI 线程然后创建您的 ChartForm 并传入该工作的结果。恕我直言,无论如何这是一个更好的设计;虽然这对您来说可能需要很多工作。

关于C# - 跨线程操作 - 在线程中创建控件,添加到主窗体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7756113/

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