Cly*_*yde 12 c# multithreading winforms
更新:只是总结一下我的问题归结为:
我希望构建.NET表单和控件不会创建任何窗口句柄 - 希望该过程被延迟到Form.Show/Form.ShowDialog
任何人都可以确认或否认这是否属实?
我有一个带有选项卡控件的大型WinForms表单,表单上有许多控件,在加载几秒钟时会暂停.我已经将它缩小到InitializeComponent中设计器生成的代码,而不是构造函数或OnLoad中的任何逻辑.
我很清楚我不能尝试在主UI线程以外的任何线程上与UI交互,但我想做的是让应用程序预先加载这个表单(运行构造函数)在后台,所以只要用户想要打开它,就可以立即在UI线程上显示.但是,在后台线程中构建时,在设计器的这一行:
this.cmbComboBox.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
Run Code Online (Sandbox Code Playgroud)
我收到了错误
在进行OLE调用之前,必须将当前线程设置为单线程单元(STA)模式.确保您的Main函数标记了STAThreadAttribute.
现在,这是设计器文件的一半,这让我希望通常这种策略可行.但是这条特殊的线似乎试图立即启动某种OLE调用.
有任何想法吗?
编辑:
我想我不是在这里说清楚.延迟似乎发生在设计人员生成的代码期间构建bazillion控件期间.
我希望所有这些初始化代码都是在没有实际尝试触摸任何真正的Win32窗口对象的情况下发生的,因为表单尚未实际显示.
我可以设置(例如)标签文本和位置来自这个后台线程的事实让我希望这是真的.然而,对于所有房产而言可能并非如此.
Ash*_*Ash 17
虽然这是不可能在一个线程创建的形式,并使用另一个线程显示它,它是绝对有可能在非主GUI线程创建的形式.目前接受的答案似乎表明这是不可能的.
Windows窗体强制执行单线程单元模型.总之,这意味着每个线程只能有一个Window消息循环,反之亦然.此外,如果例如threadA想要与threadB的消息循环交互,它必须通过诸如BeginInvoke之类的机制封送调用.
但是,如果您创建一个新线程并为其提供自己的消息循环,那么该线程将很乐意独立处理事件,直到它被告知结束消息循环.
为了演示,下面是用于在非GUI线程上创建和显示表单的Windows窗体代码:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
label1.Text = Thread.CurrentThread.ManagedThreadId.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
ThreadStart ts = new ThreadStart(OpenForm);
Thread t = new Thread(ts);
t.IsBackground=false;
t.Start();
}
private void OpenForm()
{
Form2 f2 = new Form2();
f2.ShowDialog();
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = Thread.CurrentThread.ManagedThreadId.ToString() ;
}
}
Run Code Online (Sandbox Code Playgroud)
OpenForm方法在新线程中运行并创建Form2的实例.
Form2实际上通过调用ShowDialog()给它自己独立的消息循环.如果您要调用Show(),则不会提供任何消息循环,并且Form2会立即关闭.
此外,如果您尝试在OpenForm()中访问Form1(例如使用"this"),则在尝试执行跨线程UI访问时将收到运行时错误.
该t.IsBackground=false套线为前台线程.我们需要一个前台线程,因为在没有首先调用FormClosing或FormClosed事件的情况下关闭主窗体时会立即杀死后台线程.
除了这些要点之外,Form2现在可以像任何其他形式一样使用.您会注意到Form1仍然像往常一样快乐地运行它自己的消息lopp.这意味着您可以单击按钮并创建Form2的多个实例,每个实例都有自己独立的消息循环和线程.
您需要注意跨表单访问,现在实际上是跨线程的.您还需要确保处理主窗体的关闭,以确保正确关闭任何非主线程窗体.
我觉得你的理解有点偏差。必须从创建控件的线程(而不是主 UI 线程)访问控件。您可以在应用程序中拥有多个 UI 线程,每个线程都有自己的一组控件。因此,在不同线程上创建控件将不允许您在不使用 Invoke 或 BeginInvoke 编组所有调用的情况下从主线程使用它。
编辑多个 UI 线程的一些参考:
MSDN 上的消息循环 MSDN 社交讨论 WPF 中的多线程
答案是不。
\n\n如果您在 GUI 线程以外的任何线程上创建窗口句柄,则永远无法显示它。
\n\n\n\n\n编辑:完全可以创建表单和控件并在主 GUI 线程之外的线程中显示它们。当然,如果你这样做,你只能从创建它的线程访问多线程 GUI,但这是可能的。\xe2\x80\x93 阿什利·亨德森
\n
您需要在 bg 线程上执行任何繁重的工作,然后将数据加载到 GUI 小部件中
\n| 归档时间: |
|
| 查看次数: |
12971 次 |
| 最近记录: |