C# 如何使用backgroundworker打开表单?

C# 如何使用backgroundworker打开表单?,c#,multithreading,winforms,backgroundworker,C#,Multithreading,Winforms,Backgroundworker,我有一个mdi表单,其中包含一些子表单。其中一个表单的加载需要时间。我需要使用backgroundworker来加载此表单。我尝试了这段代码,但出现了跨线程错误。实际上,我不能通过backgroundworker为我的“表单”设置mdiParent。 任何帮助都将不胜感激 代码: private void tsmiNewExpense_Click(object sender, EventArgs e) { tss_lbl1.Text = "Loading...";

我有一个mdi表单,其中包含一些子表单。其中一个表单的加载需要时间。我需要使用backgroundworker来加载此表单。我尝试了这段代码,但出现了跨线程错误。实际上,我不能通过backgroundworker为我的“表单”设置mdiParent。 任何帮助都将不胜感激

代码:

private void tsmiNewExpense_Click(object sender, EventArgs e)
    {
        tss_lbl1.Text = "Loading...";
        if (!BW1.IsBusy)
        {
            BW1.RunWorkerAsync();
        }

    }

private void BW1_DoWork(object sender, DoWorkEventArgs e)
    {
        frmNewExpense frm = new frmNewExpense();
        showChildForm(frm);
    }

    /// <summary>
    /// Checks for one instance of this form is running 
    /// </summary>
    /// <param name="frm">the form that will be shown.</param>
private void showChildForm(Form frm)
    {
        bool exists = false;
        foreach (Form item in this.MdiChildren)
        {
            if (item.Name == frm.Name)
            {
                item.Activate();
                item.StartPosition = FormStartPosition.CenterParent;
                item.WindowState = formWindowState;
                exists = true;
                break;
            }
        }
        if (!exists)
        {
            frm.MdiParent = this;//this line gets cross-thread error
            frm.StartPosition = FormStartPosition.CenterParent;
            frm.WindowState = formWindowState;
            frm.Show();
        }
    }
private void tsmiNewExpense\u单击(对象发送方,事件参数e)
{
tss_lbl1.Text=“加载…”;
如果(!BW1.IsBusy)
{
BW1.RunWorkerAsync();
}
}
私有void BW1_DoWork(对象发送方,DoWorkEventArgs e)
{
frmNewExpense frm=新的frmNewExpense();
showChildForm(frm);
}
/// 
///检查此窗体的一个实例是否正在运行
/// 
///将显示的表单。
私人作废展示儿童表格(表格frm)
{
bool exists=false;
foreach(此.MdiChildren中的表单项)
{
如果(item.Name==frm.Name)
{
item.Activate();
item.StartPosition=FormStartPosition.CenterParent;
item.WindowState=formWindowState;
存在=真;
打破
}
}
如果(!存在)
{
frm.MdiParent=this;//此行获取跨线程错误
frm.StartPosition=FormStartPosition.CenterParent;
frm.WindowState=formWindowState;
frm.Show();
}
}

这是使用同步上下文更新表单的lblTimer标签:

政务司司长:


希望获得此帮助。

必须在UI线程上创建控件和表单。您无法从其他线程安全地创建它们。由于子窗体本身的原因,您的子窗体不太可能需要很长时间才能加载。更可能的情况是,您在加载表单时正在加载数据。因此,使用后台线程加载数据,然后将数据封送回UI。您可以选择在加载数据之前或之后创建表单。@Enigmativity您说得对。没错。我错了。谢谢你的提示。:)
public partial class MainForm : Form
{
    private readonly SynchronizationContext _context;

    public MainForm()
    {
        InitializeComponent();
        // the context of MainForm, main UI thread
        // 1 Application has 1 main UI thread
        _context = SynchronizationContext.Current;
    }

    private void BtnRunAnotherThreadClick(object sender, EventArgs e)
    {
        Task.Run(() =>
                 {
                     while (true)
                     {
                         Thread.Sleep(1000);
                         //lblTimer.Text = DateTime.Now.ToLongTimeString(); // no work
                         UpdateTimerInMainThread(); // work
                     }
                 });
    }

    private void UpdateTimerInMainThread()
    {
        //SynchronizationContext.Current, here, is context of running thread (Task)
        _context.Post(SetTimer, DateTime.Now.ToLongTimeString());
    }

    public void SetTimer(object content)
    {
        lblTimer.Text = (string)content;
    }
}