在另一个线程中创建的窗体如何关闭?

7

我已经寻找了一段时间,但没有找到解决我的问题的答案。

在我的程序中,有一个任务需要几秒钟的时间,我想在执行该任务时显示一个新的表单。新表单具有加载栏和一些文本。

我需要并行显示新表单和任务,否则任务将不会开始,直到我关闭新表单。

这是我现在的解决方案:

private void loadingBar()
{
    frmLoading frm = new frmLoading("Please wait while the database is being backed up", "This might take several days.");
    frm.ShowDialog();  

}

public void Backup()
{
    Thread load = new Thread(new ThreadStart(loadingBar));
    load.Start();

    ///Execute a task.

    load.Abort(); 
}

所以,这个方法可以正常工作,但我的问题是:在加载线程中关闭表单“frm”是否更好?


1
将其视为进度条的工作方式。 将“process”作为后台线程运行,从而成为您想要显示的表单的附属品。 然后从“Main”线程调用该表单。 当加载表单作为后台线程运行时,主线程将锁定并显示您的加载表单。 这样,加载表单本身就可以跟踪进程并在完成后关闭自己。 - Nevyn
3
为什么不使用 backgroundWorker?另外,您可能需要考虑将线程的代码放在 Using() 语句中,这样它完成时会自行释放。 - Hexie
1
这样做基本上是错误的。在工作线程上显示UI存在几种非常严重的故障模式。你需要反过来做,即在UI线程上显示“加载”窗口,在工作线程上执行备份。 - Hans Passant
我尝试使用这种确切的方法放置一个加载对话框... 大约20%的时间会出现ThreadAbortExceptions。 - adipy
我遇到了与这个问题完全相同的情况。但我需要展示并隐藏一个已经设计好的表格,使用单独的线程(而不是像上面那样创建线程)。如何处理? - anandhu
4个回答

3
你可以用以下几种方式来实现...
1 - 像BendEg建议的那样,在准备好后调用frmClose 类似这样;
Invoke(new Action(Close)); 

或者

Invoke(new Action(() => frmMain.Close()));

2 - 或者您可以简单地使用后台工作程序;

最简单的方法是向您的窗体添加 BackgroundWorker,并使用提供的事件;

public Form1()
{
    InitializeComponent();
    backgroundWorker1.RunWorkerAsync();

    MessageBox.Show(@"Please wait while the database is being backed up", @"This might take several days.");
}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    Debug.WriteLine("Running"); //Execute a task
}

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    Debug.WriteLine("Ended"); //Dispose of any objects you'd like (close yor form etc.)
}

我希望这可以帮到您。

1
您可以在类级别上声明表单,并稍后使用调用关闭它。 MSDN-Windows Forms Invoke
就像这样:
    public class Class1
{
    private Form myForm;

    public Class1()
    {
        myForm = new Form();
    }

    public void DoSomeWork()
    {
        // ===================================================
        // Do Some Work...
        // ===================================================

        myForm.Invoke(new MethodInvoker(this.Hide));
    }

    public void Hide()
    {
        myForm.Hide();
    }

    public void Backup()
    {
        myForm.ShowDialog();

        Thread load = new Thread(new ThreadStart(DoSomeWork));
        load.Start();
    }
}

1
我认为这对你有用。
void YourMethod()
{
     WaitForm wf = new WaitForm();
     Invoke(new PleaseWaitDelegate(Launch),wf);
     bool val = BoolMethodDoWork();
     Invoke(new PleaseWaitDelegate(Close), wf);
                if(val)
                {
                    MessageBox.Show("Success!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                    return;
                }
                MessageBox.Show("Damn!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
}
delegate void PleaseWaitDelegate(Form form);
        void Launch(Form form)
        {
            new System.Threading.Thread(()=> form. ShowDialog()).Start();
        }

        void Close(Form form)
        {
            form.Close();
        }

0

我认为这会对你有所帮助(如果我理解你的意思是正确的):

                Parallel.Invoke(() => somemethod(), () =>
                {
                    someothertaskmethod();
                });

我放置了一些方法作为示例来演示2个任务的运行。
你需要使用正确的using语句:using System.Threading.Tasks;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接