线程完成后关闭表单

时间:2011-06-24 05:56:58

标签: c# multithreading

大家。

我有以下两种形式

  1. From1有一个按钮,当点击此Form2时会出现。

  2. From2有一个Progressbar,它正在计算并从Maximun值更新Progressbar,直到它完成,Form2将关闭。

  3. 下面的Form2代码

    public delegate void ProgressbarHandler(int value);
    public partial class Form2 : Form
    {
    
        public event WaitCallback CloseThreadEvent;
    
        private Thread t;
    
        public void OnCloseEvent(ThreadState state)
        {
            if (CloseThreadEvent != null)
                CloseThreadEvent(state);
        }
    
        public Form2()
        {
            InitializeComponent();
    
            progressBar1.Minimum = 0;
            progressBar1.Maximum = 20000;
        }
        private void Form2_Load(object sender, EventArgs e)
        {
            InitThread();
        }
    
        private void InitThread()
        {
            t = new Thread(new ThreadStart(RunThread));
            t.Start();
    
            CloseThreadEvent += new WaitCallback(CloseForm);
    
            Thread tt = new Thread(ThreadObserver);
            tt.IsBackground = true;
            tt.Start();
        }
        private void RunThread()
        {
            for (int i = 0; i < progressBar1.Maximum; i++)
            {
                progressBar1.Invoke(new ProgressbarHandler(UpdateProgressbar), i);
            }
        }
        private void UpdateProgressbar(int value)
        {
            progressBar1.Value = value + 1;
        }
    
        private void ThreadObserver()
        {
            while (t.IsAlive)
            {
                OnCloseEvent(t.ThreadState);
            }
        }
        private void CloseForm(Object state)
        {
            if ((ThreadState)state == ThreadState.Stopped)
                this.Close();
        }
    }
    

    从我的代码中,它在

    上有一个“跨线程操作无效”错误
    this.Close();
    

    请提出建议,如何根据我的目的编码。

    谢谢。

3 个答案:

答案 0 :(得分:3)

您只能从创建它们的线程访问控件。表格也是一种控制。

查看Control.Invoke

我使用类似这样的类来处理这些场景:

public static class ControlExtensions
{
    public static void Invoke(this Control control, Action action)
    {
        if (control.InvokeRequired)
        {
            control.Invoke(new MethodInvoker(action), null);
        }
        else
        {
            action.Invoke();
        }
    }
}

然后,您就可以致电this.Invoke(() => Close());关闭表单。

答案 1 :(得分:2)

非常简单的修复。

this.Invoke(new MethodInvoker(delegate { this.Close(); }));

我不知道你为什么没想到它?不是很明显吗? :P

答案 2 :(得分:0)

谢谢大家

它有效!!

    public partial class Form2 : Form
{  
    private Thread tstart, trun;

    public Form2()
    {
        InitializeComponent();

        progressBar1.Minimum = 0;
        progressBar1.Maximum = 100;
    }
    private void Form2_Load(object sender, EventArgs e)
    {
        tstart = new Thread(InitThread);
        tstart.Start();
    }

    private void InitThread()
    {
        trun = new Thread(new ThreadStart(RunThread));
        trun.Start();
        trun.Join();

        CloseForm(trun.ThreadState);
    }
    private void RunThread()
    {
        for (int i = 0; i < progressBar1.Maximum; i++)
        {
            Thread.Sleep(10);
            progressBar1.Invoke(new MethodInvoker(delegate { progressBar1.Increment(1); }));                            
        }
    }
    private void CloseForm(Object state)
    {
        if ((ThreadState)state != ThreadState.Stopped)               
            return;            
        else
        {
            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker(delegate { this.Close(); }), null);
        }
    }

    private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (tstart.IsAlive)
            tstart.Abort();
        if (trun.IsAlive)
            trun.Abort();
    }

}