- アプリ作ってて処理が重くて UI が固まるのでスレッドにしようと思って、
- 自分でスレッドクラス作ってたら、
- そう言えばコンポーネントにそんなのがあったなぁというのを思い出して調べたら、
- 簡単な BackgroundWorker というのがあったんだね(笑)
簡単な自作スレッドクラス作った後に BackgroundWorker を見つけ、お試しした後に @IT でサンプルがあった。
まぁ、それでもせっかくやったので備忘録がてらサンプルコードを残しとく。
それにしても簡単だ。。。
DoWork だけがスレッド違いなので、ここからコンポーネントを扱ってはいけない、ということさえ覚えておけばいいみたい。
途中の処理は ProgressChanged で、終了後の処理は RunWorkerCompleted でそれぞれやれば OK。
using System; using System.ComponentModel; using System.Diagnostics; using System.Threading; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// 表示直前に呼ばれる /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Form1_Shown( object sender, EventArgs e ) { EnableComponent( true ); } /// <summary> /// コンポーネントの有効/無効を切り替える /// </summary> /// <param name="enable"></param> void EnableComponent( bool enable ) { Trace.WriteLine( Thread.CurrentThread.ManagedThreadId ); #if false // フォームは以下のコンポーネントを列挙する foreach ( Control control in Controls ) { control.Enabled = enable; } #else buttonStart.Enabled = enable; buttonCancel.Enabled = !enable; #endif } /// <summary> /// スレッド関数 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker1_DoWork( object sender, DoWorkEventArgs e ) { Trace.WriteLine( Thread.CurrentThread.ManagedThreadId ); BackgroundWorker worker = sender as BackgroundWorker; for ( int i = 10; i <= 100; i += 10 ) { // キャンセル if ( worker.CancellationPending ) { e.Cancel = true; break; } // 経過通知 worker.ReportProgress( i ); Thread.Sleep( 500 ); } } /// <summary> /// 経過通知を受け取る /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker1_ProgressChanged( object sender, ProgressChangedEventArgs e ) { Trace.WriteLine( Thread.CurrentThread.ManagedThreadId + ":" + e.ProgressPercentage ); } /// <summary> /// スレッド終了後に呼ばれる /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void backgroundWorker1_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) { MessageBox.Show( e.Cancelled.ToString() ); EnableComponent( true ); } private void buttonStart_Click( object sender, EventArgs e ) { #if true Trace.WriteLine( Thread.CurrentThread.ManagedThreadId ); EnableComponent( false ); backgroundWorker1.RunWorkerAsync(); #else EnableComponent( false ); Thread.Sleep( 3000 ); MessageBox.Show( textBoxName.Text ); EnableComponent( true ); #endif } private void buttonCancel_Click( object sender, EventArgs e ) { backgroundWorker1.CancelAsync(); } } }