2011-06-24 21 views
0

みんな。スレッドが終了したときにフォームを閉じる

このForm2のが表示されますクリックしたときに、私はFROM1

  1. により、次のように2つのフォームは、ボタンを持っていました。

  2. From2にはプログレスバーがあり、それが終了するまでMaximun値からProgressbarを数えて更新します。Form2が終了します。この私のコードからの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(); 

の「クロススレッド操作ではない有効な」エラーが発生したコーディングする方法の提案を教えてください私の目的に従ってください。

ありがとうございます。

答えて

2

かなり簡単な修正です。

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

なぜあなたはそれを考えなかったのですか?それは明白ではありませんか? :P

+0

私はとても初心者です。 : – Yoonmy

+1

または、単に:Invoke(新しいMethodInvoker(Close)); – Sean

3

コントロールは、作成されたスレッドからしかアクセスできません。フォームもコントロールです。

Control.Invokeをご覧ください。そして、あなたは、フォームを閉じるためにthis.Invoke(() => Close());を呼び出すことができるだろう

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

私は、これらのシナリオを処理するために、次のようなクラスを使用します。

+0

'Close'メソッドが' Action'デリゲートと既に一致しているため、さらに短い 'Invoke(Close)'を使用します。 –

+0

well spotted: –

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

} 
+0

スレッドを開始してスレッドを開始するのが理にかなっています。また、スレッド状態をチェックするのは意味がありませんし、スレッドから呼び出されていることを知っているInvokeRequiredもありません。 –

関連する問題