• ベストアンサー

スレッドの中断についての質問

現在、C#でプログラミングを開発しております。初心者ですので、よろしくお願いします。 public delegate void MyMethod(); private Thread t1=null ; public void btn_Download_Click(object sender, EventArgs e) //Go! {   Thread t1 = new Thread(new ThreadStart(DownloadThread_HTTP));   t1.IsBackground = true; t1.Start(); } public void DownloadThread_HTTP() // download Thread { MyMethod DOWNLOAD_with_HTTP = new MyMethod(this.DOWNLOAD_with_HTTP); this.BeginInvoke(DOWNLOAD_with_HTTP); } public void DOWNLOAD_with_HTTP() { ...... } private void button2_Click(object sender, EventArgs e) //pause button { t1.Join(); } コードは 以上です。コンパイラは大丈夫ですけど、プログラムを実行するときに button2をクリックすると NullReferenceException例外エラーが出ます。t1の値がNullのためっていうことをわかりますけど、どうやれば t1の値がNullにならないのですか? ご教授ください、お願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • E-Yu
  • ベストアンサー率40% (2/5)
回答No.3

おそらくANo.1さん、ANo.2さんの仰っていることで合っていると思います。 // ** これはメンバ変数 ** private Thread t1=null ; public void btn_Download_Click(object sender, EventArgs e) //Go! {   // ** これはローカル変数!! メンバのt1が参照されていない ** //  Thread t1 = new Thread(new ThreadStart(DownloadThread_HTTP));   // ↓こうする   t1 = new Thread(new ThreadStart(DownloadThread_HTTP));   t1.IsBackground = true; t1.Start(); } C#はやってないので分かりませんが、原因はこれで合っているような気がします。 これでbtn_Download_Click()関数がbutton2_Click()関数よりも先に呼ばれていればいいと思います。

その他の回答 (3)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

> 自分もprivate Thread t1 = nullのところの設定が余計だと思います 逆ですよ private Thread t1 = null; は必要です btn_Downlod_Clickイベントの中の t1は Thread型宣言をしない状態で使わないといけないってことです

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

Ano.1氏の回答のように クラスに宣言した private Thread t1 = null; が btn_Download_Clickイベントでは使用されていません btn_Download_Clickイベントの中で宣言されたローカル変数t1でスレッドを起こしています これに対して button2_Click側ではローカル変数の宣言は無いのでクラスで宣言されたt1を参照します しかし クラス宣言のt1へは何も代入されていないのでnullのままということになります 変数のスコープについて調べてみましょう

kindo_2007
質問者

補足

自分もprivate Thread t1 = nullのところの設定が余計だと思います。 が、private Thread t1 のままでも、t1の値がNullを既定に進行しています。(例外の詳細に見える) 有難うございます。

回答No.1

public void btn_Download_Click(object sender, EventArgs e) //Go! の中で Thread t1 = new Thread(new ThreadStart(DownloadThread_HTTP)); としていますが、 先頭の Thread が余計なのでは? それがあるせいで新しい変数宣言と判断されているんじゃないかと思います。 動作確認はしていません。

kindo_2007
質問者

補足

有難うございます。新しい変数宣言をしても、例えば: Thread t2 = new Thread(new ThreadStart(DownloadThread_HTTP));としたら t2.join(); ボタン2を押すと、ThreadStateExceptionの例外エラーが出ます。 困ります。 有難うございます。

関連するQ&A

  • C#のnew Thread以下のコード分解

    new Thread以下のコードを分解できますか? ====================== private void button1_Click(object sender,EventArgs e) { new Thread(new ThreadStart(delegate() { AllocConsole(); //開始============== for(uint i = 0;i < 100;++i) { Console.WriteLine("Hello " + i); } FreeConsole(); //終了============== })).Start(); } =================== 以上

  • 別スレッドとイベントの終了手順について

    C#の質問になります。 メインフォーム上で別スレッドを起動し、別スレッドからのイベントで メインフォーム上のテキストボックスにメッセージを表示しています。 サンプルソースはフォームにボタン2個とテキストボックス1個を貼り 付けたものになり、ボタン1でスレッド起動、ボタン2で停止させてい ます。 正常パターンでボタン1とボタン2を交互に押下すると意図したとおり テキストボックスにメッセージが出力されます。 このプログラムで、ボタン1を押下し別スレッドが起動した状態で、 フォームの×ボタンを押下すると別スレッドの停止処理中にJoin() 呼び出しで永久に止まってしまいます。 止めるべきスレッド中でイベント(OnTraceEvent)を呼び出している のが問題のような気がします。(この処理がなければ正常) このような時の終了手順の王道的なものはありますでしょうか。   public partial class Form1 : Form   {     ThreadTest _thread = null;     public Form1()     {       InitializeComponent();     }     private void button1_Click( object sender, EventArgs e )     {       if ( this._thread == null )       {         this._thread = new ThreadTest();         this._thread.TraceEvent += new ThreadTest.TraceEventHandler( OnTrace );         this._thread.Open();       }     }     private void button2_Click( object sender, EventArgs e )     {       if ( this._thread != null )       {         this._thread.Close();         this._thread.TraceEvent -= new ThreadTest.TraceEventHandler( OnTrace );         this._thread = null;       }     }     private void OnTrace(String message)     {       if ( this.IsHandleCreated == false )       {         return;       }       MethodInvoker process = (MethodInvoker)delegate()       {         textBox1.AppendText( message + "\r\n" );       };       if ( this.InvokeRequired )       {         this.Invoke( process );       }       else       {         process.Invoke();       }       return;     }     private void Form1_FormClosed( object sender, FormClosedEventArgs e )     {       //フォームの×ボタンを押下した時にスレッドを停止しないと       //破棄されたコントロールを操作しようとするため下記を追加       if ( this._thread != null )       {         this._thread.Close();         this._thread.TraceEvent -= new ThreadTest.TraceEventHandler( OnTrace );         this._thread = null;       }     }   }   class ThreadTest   {     public delegate void TraceEventHandler( String message );     public event TraceEventHandler TraceEvent;     protected virtual void OnTraceEvent( String message )     {       TraceEventHandler TraceEventTemp = TraceEvent;       if ( TraceEventTemp != null )       {         TraceEventTemp( message );       }     }     private Thread _threadLoop = null;     private volatile Boolean _threadFlag = false;     public void Open()     {       //スレッド開始       if ( this._threadLoop == null )       {         this._threadLoop = new Thread( new ThreadStart( Loop ) );         this._threadLoop.Start();         while ( !this._threadLoop.IsAlive ) ;       }     }     public void Close()     {       //スレッド停止       if ( this._threadLoop != null )       {         this._threadFlag = false;         //this._threadLoop.Abort();//ここを有効にすればとりあえず終了する         this._threadLoop.Join();         this._threadLoop = null;       }     }     public void Loop()     {       this._threadFlag = true;       while ( this._threadFlag )       {         OnTraceEvent( DateTime.Now.ToString( "yyyy/MM/dd hh:mm:ss:fff" ) );         Thread.Sleep( 100 );       }     }   }

  • C# フォーム追加後、旧フォームを閉じたい

    前略 ・C#で教えてください。 ・Form1 からshowDiag()メソッドでForm2をつくります。Form2が表示されたら非アクティブとなったForm1を閉じたいのですが どのようにしたらよいのかおしえてください。  下記は、Close() メソッドで Form2側から閉じようとしたプログラムですがFrom1を閉じることができません。 よろしくお願いします。 //----------------------------------------------- namespace formClose { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 form2 = new Form2(); form2.ShowDialog(); } }   public partial class Form2 : Form { public Form2() { InitializeComponent(); } private void Form2_Load(object sender, EventArgs e) { Form1 form1 = new Form1(); form1.Close(); //Form1が閉じない!! } private void button1_Click(object sender, EventArgs e) { this.Close(); //Form2を閉じる }    } } 以上

  • C#でオブジェクトの有無を取得する

    オブジェクトが作られている時と作られていない時で処理をわけたいのですがうまくいきません。 この書き方の何がまずいのでしょうか? namespace オブジェクト検索 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Control c = Controls["form2"]; if (c != null) { ((TextBox)c).Text += "*"; } } private void button2_Click(object sender, EventArgs e) { Form2 form2 = new Form2(); form2.Show(); Application.DoEvents(); } } } ボタン2を押した時に新しいフォームが立ち上がり、そのフォームがあるときは*が出るようにしたいです。

  • Visual c# スレッド

    プログラム初心者です。 Visual c#にてスレッド関数を使ったプログラムを見よう見まねで 作りました。 スタートボタンを押すとピクチャーボックスの位置が 左から右へ移動し、ストップボタンを押すと止まる。 ピクチャーボックスの位置をテキストボックスに表示する。 というプログラムのつもりです。 デバックの状態でスタートボタンを押すとエラーメッセージが出て テキストボックスに位置を書き込むの関数のところが緑色にハイライトされます。エラーの内容は「有効でないスレッド間の操作」とありますが、どうしたら良いのか分かりません。 エラーの直し方を教えてください。 プログラムコードは以下です。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Threading; namespace bit_map_08._1._ { public partial class Form1 : Form { private Thread thread; static private int Position = 0; static private int i; static bool BtnOnFig; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { thread = new System.Threading.Thread(newSystem.Threading.ThreadStart(MainThread)); thread.Start(); } private void PointMove() { if (i < 300) { i = i + 1; Position = Position + i; textBox1.Text = Convert.ToString(Position); pictureBox1.Left = (Position); } if (i == 300) { i = 0; } } private void MainThread() { while( true ) { Thread.Sleep(100); if (BtnOnFig == true) { PointMove(); } } } private void button1_Click(object sender, EventArgs e) { BtnOnFig = true; } private void button2_Click(object sender, EventArgs e) { BtnOnFig = false; } } }

  • PeekMessage()について

    Windowsフォームアプリケーションです。 ループさせたいイベント(button1)中に、button2のイベントを行いたいのでPeekMessage()を使って以下のようにしました。 private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { while(1){ PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); TranslateMessage(&msg); DispatchMessage(&msg); // ループさせたいイベント ・・・・・・・・・・・・・・・・・・・・ } } private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) {    ・・・・・・・・・・・・・・・・・・・・ } アプリケーション起動後、button1をクリックし、後にbutton2をクリックしようとすると代わりにbutton1がクリックされてしまいます。 PeekMessage()の使い方が間違っているのでしょうか。

  • イベントハンドラ関数について

    現在VC++/CLR 2005 でプログラミングをしています。 基本的な事柄かもしれませんが、質問させてください  以下の2つのボタンのイベントハンドラ関数があった場合 //ボタン1のイベントハンドラ関数 private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) String^ str = textBox1->Text } //ボタン2のイベントハンドラ関数 private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { } ボタン2をクリックしたときの動作とボタン1の動作を同じにしたいと思っています。 その場合は private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) String^ str = textBox1->Text } //ボタン2のイベントハンドラ関数 private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { String^ str = textBox1->Text } のようにボタン2のイベントハンドラ関数をボタン1と同じように書けばいいのですが イベントハンドラ関数の処理が膨大になった場合を考えて省略する 書き方は無いのでしょうか?(以下の場合ですとエラーが起こってしまいます。) private: System::Void button2_Click(System::Object^ sender, System::EventArgs^ e) { button1_Click(); } 宜しくお願いします

  • Thread.Abortメソッド後の処理について

    Thread.abortメソッドについて分からないことがあったので,助言が頂けると嬉しいです. Thread.Abort () を発生させると,通常そこでスレッドが終了するということなので,その後のスレッド内の処理はスルーされると思っていたのですが,下記コードですとその後の pictureBox1.Image = null;も実行されている様です. mainでスレッド作成→threadAの停止になると考えていたのですが,delegate内では反映されないのでしょうか? Thread thread_a; //スレッド delegate void Del(); private void main(object sender, EventArgs e) { //スレッドを開始 thread_a = new Thread(new ThreadStart(threadA)); thread_a.Start(); } private void threadA() { new Thread(new ThreadStart(delegate { Invoke((Del)delegate { thread_a.Abort(); //画像を消去する pictureBox1.Image = null; }); })).Start(); }

  • スレッドについて

    お世話様です。 Windowsのスレッドについて質問です。(WinXP C#.NET2003) 以下のようなコードでスレッドを作成した場合、どうなるのか教えてください。 private void BTN_input_Click(object sender, System.EventArgs e) { Thread iwth = new Thread( new ThreadStart(InputWaitThread) ); iwth.Start(); } (1)iwthは動的に割り当てたのでBTN_input_Click関数内でのみ有効だと  思うのですが、BTN_input_Click関数を抜けてしまったあとは、  InputWaitThreadを実行するスレッドは  どういう位置づけになるのでしょうか?  (ゾンビプロセスですか?) (2)また、このコードを含むアプリケーションの終了時、  InputWaitThreadがまだ終了していない場合は、  強制的に終了されるのでしょうか? (3)InputWaitThreadが必ず終了するという保障がない場合には、  KILLしてやらなければいけないと思いますが、動的に割り当てたので  ハンドラがおらずKILLできませんが、どうすればいいのでしょうか?  (静的に割り当てておくしかないのでしょうか?) 以上、よろしくご教授願います。(@±@)

  • C# Formの操作

    Form2 form2 ; // 子 Form Form3 form3 ; // 子 Form private void button1_Click(object sender, System.EventArgs e) { form2 = new Form2() ; this.AddOwnedForm(form2) ; // 親 Form が form2 を所有する form2.Show() ; } private void button2_Click(object sender, System.EventArgs e) { form3 = new Form3() ; this.AddOwnedForm(form3) ; // 親 Form が form3 を所有する form3.Show() ; } 上記のようにボタン一つに対して1つのFormに対する処理をするのではなく,ボタン1つに対して 複数のFormを処理する.つまり 例えば,Form1,2,3とあったとして,Form1のボタンを押してFrom2を開き,そこで何らかの処理を したものをForm1に反映する.または,From3のボタンを押してForm2を開きそこで何らかの処理を 行いForm3に反映する. この場合,Form1とForm3のどちらのFormのボタンが押されたか判断しないといけないと思うのですが,ここの処理がうまくいきません. どちらかのFormのボタンを押してForm2を表示し,どちらかのFormに反映させる所までは出来たのですが,両方の判断材料を入れて,どちらのFormのボタンを押されたか判断する際に,押されなかった方が「null」となりエラーになります. 下記にこの判断部分を掲載いたします.どなたかご教授よろしくお願いいたします. Form1 public int but = 0; public int butt1; public string DB; public string HDB; public Form2 f2 = null; private void mybutton1_Click(object sender, EventArgs e) { butt1 = 1; ・ ・ ・ public int Ye=0; private void button43_Click(object sender, EventArgs e) { butt1 = 0; From2 public partial class Form2 : Form { Form1 f1; Form3 f3; public Form2(Form1 f) { f1 = f; // メイン・フォームへの参照を保存 InitializeComponent(); } public Form2(Form3 f) { f3 = f; // メイン・フォームへの参照を保存 InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { #region int Pin1 = f1.butt1; int Pin3 = f3.butt3; Form3 Form1と基本的には同じです.

専門家に質問してみよう