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

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

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

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

3回答

16782閲覧

タイマーの中で非同期処理はやっちゃだめですか?

退会済みユーザー

退会済みユーザー

総合スコア0

C#

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

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

0クリップ

投稿2020/06/17 11:44

編集2020/06/17 12:04

助けてほしいこと

こんにちは。
今、C#の基本をやっています。
Form1クラスでタイマーをセットしているのですが、timer.Stop()でエラーになります。
これはどのようにすればよいか教えてほしいのです。

詳細

タイマーをセットしているところ

C#

1//タイマー 2System.Timers.Timer timer; 3 4private void Setimer(int time) 5{ 6 // タイマーの生成 7 timer = new System.Timers.Timer(time); 8 timer.Elapsed += (sender, e) => 9 { 10 test_async(); 11 timer.Stop(); 12 label_Timer.Text = "タイマーとめたよ"; 13 }; 14 15 timer.Start(); 16 label_Timer.Text = "タイマーはじめました"; 17}

タイマー時間経過で呼び出している関数

C#

1private async Task test_async() 2{ 3 txtdata = textBox.Text; 4 if (txtdata == "その1") 5 { 6 while (Test.Proc1(txtdata) == false) 7 { 8 //停止になってたらとめる 9 if (Stopflg == true) break; 10 //再読み込みまで100ms空ける 11 await Task.Delay(100); 12 } 13 return; 14 } 15 16 // 非同期で動かす(固まっちゃうので) 17 await Task.Run(async () => 18 { 19 while((Test.Proc2(txtdata) == false) 20 { 21 //停止になってたらとめる 22 if (Stopflg == true) break; 23 //100ms待ってから 24 await Task.Delay(100); 25 } 26 }); 27 return; 28}

わからないこと

C#

1test_async();

がなければ、エラーになりませんので、ここが悪いとは思います。

C#

1await test_async();

にしてもだめでしたので、悩んでいます。
タイマーの呼び出しの中で非同期処理をしている関数を呼んではいけない、ということですか?

参考

参考にさせていただいたのはこちらの中ほどのコードでした。
https://webbibouroku.com/Blog/Article/cs-timer

エラー

例外がスローされました: 'System.InvalidOperationException' (System.Windows.Forms.dll の中) 型 'System.InvalidOperationException' の例外が System.Windows.Forms.dll で発生しましたが、ユーザー コード内ではハンドルされませんでした 有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'label_Timer' がアクセスされました。

改めて

右も左もわからず、思うがまま組んでみてます。
そもそも、それじゃダメ、という意見もあるかと思います。
よろしければ、教えていただければうれしいです。

よろしくお願いいたします(- -)(_ _)ペコリ

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

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

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

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

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

y_waiwai

2020/06/17 11:50

エラーメッセージを提示しましょう いらぬ加工をせず、出たそのママを提示してください
退会済みユーザー

退会済みユーザー

2020/06/17 11:58

ありがとうございます 記入しました
BluOxy

2020/06/17 12:00 編集

コントロールが作成されたスレッド以外のスレッドからlabel_Timerにアクセスしたことが原因と書かれています。添付されたコードにそのような処理は書かれていないので、上記の例外と添付されたコードは関係がないように見えます。
退会済みユーザー

退会済みユーザー

2020/06/17 12:01

すみません、変数名label_Timerが上のコードでいうlabelなんです。 短くしようとして変えてました。
BluOxy

2020/06/17 12:05

誤解が生じかねないので、質問には実際のコードを記載してください。
guest

回答3

0

test_async();

timer.Stop();

タイマーを止める前に、test_async()を呼び出しますが、問題ありません?
多重になって問題を起こす気がします。

投稿2020/06/17 12:25

pepperleaf

総合スコア6385

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

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

BluOxy

2020/06/17 12:30

InvalidOperationException とは別の問題が起きそうですね。
退会済みユーザー

退会済みユーザー

2020/06/17 12:52

ありがとうございます。さらに問題あるのですか。 タイマーは一回きりのつもりで書いていたのですが、多重になるんですね・・・(´・ω・`) 順番ですか。 タイマー止めてからテスト関数して、デリゲート?でラベル書き込みしてみます。 (ラベルは外から見えるようにしたかっただけなので、別になくてもいいのですが・・・)
BluOxy

2020/06/17 13:34

timer.Stop(); test_async(); と順番を入れ替えたら良いです。 現在のコードの場合はtimer.Stop()が呼ばれる前に次のイベントが実行され、多重にtest_asyncが呼ばれる場合があります。
退会済みユーザー

退会済みユーザー

2020/06/17 13:43

ありがとうございます。 その順番にしてみます。 ただ、「次のイベント」というものがしっくり来てないので、間違ったコードでも何が起こるか確認してみます! ちょっとしたことでエラーが出るの難しいですね。 がんばります!
guest

0

ベストアンサー

System.Timers.Timer クラスを見ると、下記のように記載されています。

SynchronizingObject プロパティが null場合、ThreadPool スレッドで Elapsed イベントが発生します。

label_TimerはWindows Formsのコントロールですから、そのコントロールに対して変更ができるスレッドはエラーメッセージに出ている通り「コントロールが作成されたスレッド」だけです。このスレッドは一般的にメイン スレッドと呼ばれます。

それ以外のスレッド(すなわちThreadPoolスレッド もといtimer.Elapsedイベント)でlabel_Timer.Text = "タイマーとめたよ";のようにWindows Formsのコントロールに対してアクセスを行うとInvalidOperationExceptionが発生します。これが今回の原因です。

解決策として一般的な方法はControl.Invoke メソッドを使ってメイン スレッドに処理を委譲することです。


今回の問題に関連する記事が公式にありますので、参考にしてください。
方法 : Windows フォーム コントロールをスレッド セーフに呼び出す

投稿2020/06/17 12:18

BluOxy

総合スコア2663

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

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

退会済みユーザー

退会済みユーザー

2020/06/17 12:24 編集

ありがとうございます。 test_async();を足したタイミングでエラーになったと思い込んでましたので、これのせいかと思っていましたが、label_Timerを触ったのがダメだったんですね。 (勘違いの可能性もありますが、test_async前は動いていた気がしてます… リンク先を読ませていただいた限りでは、安全「でない」ということなので、たまたま動いてただけっぽいですが…) もう少しじっくりいただいたリンク読んでみます! ありがとうございました。
guest

0

そのエラーメッセージを読んでください。
別のスレッドからコントロールを操作したがための例外です

投稿2020/06/17 12:00

y_waiwai

総合スコア88042

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問