質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

3回答

4852閲覧

C# スレッド実行のエラー

dekky0910

総合スコア93

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

2クリップ

投稿2017/05/23 05:28

###前提・実現したいこと
お世話になります。
今回スレッドの勉強でコードを書いていたのですが、コードの書き方でエラーが起きたり起きなかったりしてしまっているので原因を知りたく質問させていただきました。

フォームにテキストボックスを1つだけ置き下記のコードを記入します。

###該当のソースコード

C#

1namespace thread 2{ 3 public partial class Form1 : Form 4 { 5 private Thread test; 6 private string txt; 7 public Form1() 8 { 9 InitializeComponent(); 10 11 12 } 13 14 private void Form1_Load(object sender, EventArgs e) 15 { 16 17 test = new Thread(new ThreadStart(textchange)); 18 test.Start(); 19 20 } 21 22 public void textchange() 23 { 24 txt="実行終了"; 25 textBox1.Text = txt; 26 27 28 } 29 } 30} 31上記のコードだとアイテムにアクセスできずエラーが起きるのはわかるのですが 32 33namespace thread 34{ 35 public partial class Form1 : Form 36 { 37 private Thread test; 38 private string txt; 39 public Form1() 40 { 41 InitializeComponent(); 42 test = new Thread(new ThreadStart(textchange)); 43 test.Start(); 44 45 } 46 47 public void textchange() 48 { 49 txt="実行終了"; 50 textBox1.Text = txt; 51 52 53 } 54 } 55} 56 57これで実行すると動いてしまいます。

なぜコンストラクタでスレッドを実行させると正常終了してしまうのでしょうか?

ご教授よろしくお願いします。

###補足情報(言語/FW/ツール等のバージョンなど)
VisualStudio2013

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hsk

2017/05/23 05:53

エラー(例外)の内容(メッセージ)をご提供いただけますか?「>上記のコードだとアイテムにアクセスできずエラーが起きるのはわかるのですが」とありますが、UIスレッドを別のスレッドから操作しようとしたための例外なようにも思えますので、何の例外かでそこをはっきりできます。
dekky0910

2017/05/23 05:55

例外内容はこちらです。型 'System.InvalidOperationException' のハンドルされていない例外が System.Windows.Forms.dll で発生しました 追加情報:有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'textBox1' がアクセスされました。
guest

回答3

0

コンストラクタで呼ばれたかどうかは問題ではなく、textBox1.Text = txtした時のコントロールの状態に依存するのだと思います。 コンストラクタで呼ばれても、

C#

1public void textchange() 2{ 3 System.Threading.Thread.Sleep(3000); 4 txt = "実行終了"; 5 textBox1.Text = txt; 6}

とすれば、Form1_Load の時と同様に落ちます。
Sleepせずに呼ばれて即終了している場合は、単純に(Load前なので)コントロールにリソース等の割り当てがされる前だからではないでしょうか(恐らく)

投稿2017/05/23 06:06

編集2017/05/23 06:09
ebiryo

総合スコア797

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dekky0910

2017/05/24 04:33

回答が遅くなってしまい申し訳ございません。 回答の通りでHandleが作成される前に実行されたためキャッチしなかったみたいです。
guest

0

こんにちは。下記リンクをご覧ください。
https://msdn.microsoft.com/ja-jp/library/ms171728.aspx

NET Framework は、スレッド セーフでない方法でコントロールにアクセスしていることを検出するのに役立ちます。 デバッガーでアプリケーションを実行しているときに、コントロールを作成したスレッド以外のスレッドがそのコントロールを呼び出そうとすると、デバッガーは InvalidOperationException を発生させ、"コントロールが作成されたスレッド以外のスレッドからコントロール 'コントロール名' がアクセスされました。" というメッセージが示されます。

フォームのコントロールは、複数のスレッドから操作されてしまうと誤動作をすることがあります(単なるスレッドと異なり、メッセージポンプなどの特殊な構造を扱っています)。それを防ぐため、デバッグバージョンの実行モジュールではあえてそれを検知して例外を発生させています。

フォームを扱うスレッド(通称UIスレッド)とは別スレッドから、フォーム上のコントロールを操作したいときは、Invoke メソッドを使用し、別スレッドからUIスレッドへ操作を依頼する方法で行います。面倒くさいですけれども...

http://www.atmarkit.co.jp/ait/articles/0506/17/news111.html

投稿2017/05/23 06:05

編集2017/05/23 06:07
hsk

総合スコア728

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dekky0910

2017/05/24 04:35

回答が遅くなり申し訳ございません。 誤作動を起こさないためにやはりコンストラクタでは作成しないほうがいいのですね。
guest

0

ベストアンサー

Control.cs のソースを見ると、2833 行目に該当する例外がスローされています。
InvokeRequired など他も追って見ていただけるとわかるのですが、Handle が作成された後に別スレッドから Handle がアクセスされるとこの例外がスローされます。
コンストラクタ内で別スレッドを作った場合、まだ Handle が作成されないうちにアクセスされますが、Load イベントが呼ばれる時には既に Handle は作成されています。

投稿2017/05/23 06:22

編集2017/05/23 06:31
Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dekky0910

2017/05/24 04:33

回答が遅くなり申し訳ございません。 Handleが作成される前に実行され処理が正常に終了しているように見えるということですね。
Zuishin

2017/05/24 05:23

ハンドル作成前に行われた処理はハンドル作成後に有効になりますので、正常終了と言って構わないと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問