Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/284.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 窗体显示不使用线程_C#_.net_Winforms - Fatal编程技术网

C# 窗体显示不使用线程

C# 窗体显示不使用线程,c#,.net,winforms,C#,.net,Winforms,我正在创建一个应用程序,其中它启动一个FormSelect(),要求用户在列表中选择一项,当用户按下“选择”按钮时,它将创建一个新的MainForm()实例,隐藏FormSelect并显示MainForm,但它不工作,我所做的所有测试都出现异常 以下是一些代码: static class Program { public static MainForm mainForm; /// <summary> /// The main entry

我正在创建一个应用程序,其中它启动一个FormSelect(),要求用户在列表中选择一项,当用户按下“选择”按钮时,它将创建一个新的MainForm()实例,隐藏FormSelect并显示MainForm,但它不工作,我所做的所有测试都出现异常

以下是一些代码:

static class Program {
        public static MainForm mainForm;
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FormSelect());
        }
    }
正如您在上面看到的,我正在使用一个任务来启动MainForm,这样它就不会冻结我的UI和“加载spiner”

但是当它尝试使用.Show()时,我得到了一个跨线程异常,因此我尝试使用以下方法调用该操作:

this.Invoke(new MethodInvoker(delegate () { Program.mainForm.Show(); }));
但是使用上面的方法,我得到一个例外,说:

System.Windows.Forms.dll中发生“System.ComponentModel.Win32Exception”类型的异常,但未在用户代码中处理

其他信息:创建窗口句柄时出错

如果我删除startMatInfo方法中的“await Task.Run()…”,一切正常,但它会完全阻塞FormSelect UI


我怎样才能避免这个问题?谢谢大家!

你不能那样做

如果没有一个可靠地再现问题的好方法,就不可能确定您的场景的最佳解决方案是什么。但UI对象必须创建并仅在UI线程中使用。无法在工作线程中创建
MainForm
实例

因为您的代码示例不完整,所以不清楚您为什么要首先使用
Task.Run()
创建
MainForm
实例。代码所做的只是调用构造函数,而构造函数无论如何都不应该是耗时的操作

如果您需要执行一些耗时的初始化,那么应该将其从
MainForm
类中抽象出来,并将其放入其他类中,在完全初始化后可以传递给
MainForm
。然后,您可以通过调用
Task.Run()
(但仍然不在构造函数中…创建对象,然后如果需要异步调用初始化该对象的方法,请执行该操作)来初始化另一个类

例如:

private async void b选择\u单击(对象发送方,事件参数e){
loadingSpiner.Visible=true;
btselect.Enabled=false;
int index=listProcess.SelectedIndex;
MainFormData数据=等待启动通知(索引);
Program.mainForm=新的mainForm(数据);
this.Hide();
Program.mainForm.Show();
}
专用异步任务startMainForm(int索引){
等待任务。运行(()=>{
MainFormData data=新的MainFormData();
初始化(运行进程[索引]);
返回数据;
});
}
类MainFormData
{
public MainFormData(){…}
//你们并没有说“runningProcess[index]”是什么,所以这里的占位符。。。
公共无效初始化(对象o){…}
}
差不多吧。当然,调整以适应你的需要


当然,另一个类必须只初始化非UI方面。即用户界面下的数据。由于创建UI对象通常并不耗时,因此我认为这在您的情况下是可行的。如果您觉得UI本身的初始化非常耗时,那么您应该寻求帮助,找出问题所在并解决问题。当然,这里没有一个好的MCVE,我也没有什么可以特别评论的。

你不应该在uithread上打开任何ui。除了用来调用
应用程序的线程之外,你不能在任何线程上创建ui。运行
——更常见的称为ui线程。我认为“默认形式”在Program.cs中指定运行应用程序时启动。在Program.cs中,您应该能够找到启动该表单的调用,该调用应该是阻塞的(因为此时我们是单线程的),然后添加代码以启动下一个表单?谢谢,我将MainForm构造函数中的所有逻辑(除了InitializeComponent())移到了返回“MainFormData”的任务中,所以我刚刚制作了一个新的主窗体(FormData),它工作得很好。再次感谢
this.Invoke(new MethodInvoker(delegate () { Program.mainForm.Show(); }));
private async void btnSelect_Click(object sender, EventArgs e) {
    loadingSpiner.Visible = true;
    btnSelect.Enabled = false;

    int index = listProcess.SelectedIndex;

    MainFormData data = await startMainForm(index);

    Program.mainForm = new MainForm(data);
    this.Hide();
    Program.mainForm.Show();
}

private async Task<MainFormData> startMainForm(int index) {
    await Task.Run(() => {
         MainFormData data = new MainFormData();
         data.Initialize(runningProcess[index]);
         return data;
    });
}

class MainFormData
{
    public MainFormData() { ... }

    // You don't say what "runningProcess[index]" is, so placeholder here...
    public void Initialize(object o) { ... }
}