【问题标题】:Closing a form that is created in another thread关闭在另一个线程中创建的表单
【发布时间】:2013-08-12 13:14:15
【问题描述】:

一段时间以来,我一直在寻找特定问题的答案,但没有成功。

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

我需要显示与任务并行的新表单,否则在我关闭新表单之前任务不会启动。

这是我现在的解决方案:

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”以使其停止不是更好吗?

【问题讨论】:

  • 把它当作进度条工作。将“进程”作为从属于您要显示的表单的后台线程运行。然后从“主”线程调用该表单。主线程将锁定您的加载表单显示,而加载表单作为后台线程运行。这样,加载表单本身可以跟踪进程并在结束后自行关闭。
  • @Dave 为什么不直接使用backgroundWorker?另外 - 您可能需要考虑将 Thread 的代码放在 Using() 语句中,然后它会在完成时自行处理。
  • 这根本就是错误的做法。在工作线程上显示 UI 有几种非常糟糕的失败模式。您需要以相反的方式执行此操作,在 UI 线程上显示“加载”窗口,在工作线程上执行备份。
  • 我尝试使用这种确切的方法放入加载对话框...大约 20% 的时间以 ThreadAbortExceptions 结束。
  • 我面临着同样的问题。但我需要显示和隐藏我使用单独线程设计的已经存在的表单(不是像上面那样使用线程创建)。这样做的方法是什么?

标签: c# multithreading winforms


【解决方案1】:

你可以通过几种方式做到这一点......

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.)
}

我希望这会有所帮助。

【讨论】:

    【解决方案2】:

    您可以在类级别声明表单,然后通过调用将其关闭。 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();
        }
    }
    

    【讨论】:

      【解决方案3】:

      我认为这对你有用。

      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();
              }
      

      【讨论】:

        【解决方案4】:

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

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

        我以方法为例来演示 2 个正在运行的任务。

        你需要使用正确的using语句using System.Threading.Tasks;

        【讨论】:

          猜你喜欢
          • 2013-08-21
          • 2015-06-14
          • 1970-01-01
          • 1970-01-01
          • 2021-05-04
          • 2020-05-29
          • 1970-01-01
          • 2014-10-07
          • 1970-01-01
          相关资源
          最近更新 更多