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

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

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

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

1回答

2002閲覧

C# Taskのキャンセル処理を実装したいです

Mighty

総合スコア1

C#

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

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

1グッド

1クリップ

投稿2020/05/05 10:44

前提・実現したいこと

Visual Studio(C#)でストップウォッチ計測アプリを開発しています。計測機能に必要な動作は以下のとおりです。

動作1. フォームをクリック(1回目) ⇒ Beep音とともにストップウォッチ開始
動作2. 8秒後,9秒後にBeep音、10秒後に1秒間Beep音を鳴らす
動作3. フォームをクリック(2回目) ⇒ 計測値A秒を取得、ストップウォッチ停止
動作4. フォームをクリック(3回目) ⇒ ストップウォッチ開始(0秒から)
動作5. 8秒後,9秒後にBeep音、10秒後に1秒間Beep音を鳴らす
動作6. フォームをクリック(4回目) ⇒ 計測値B秒を取得
動作7. フォームをクリック(5回目) ⇒ 計測値C秒を取得、ストップウォッチ停止

上記を1セットとして、5セット計測します。(3×5セット=合計15個の計測値を取得します。)ただし、用途の都合で、5セット目が完了するまでクリック回数によってアプリを制御するため、フォームクリック(6回目)が2セット目の動作1となり、そこからフォームクリック(10回目)までが2セット目になります。この計測機能を5セット目完了、フォームクリック(25回目)まで、フォームクリック回数によって動作制御します。

8秒後,9秒後および10秒後に鳴らすBeep音をシングルスレッドで実装した場合、ストップウォッチの計測表示(stopwatchクラスのsw.Elapsedを用いてTimerクラスでミリ秒単位で計測結果を表示)が、Beep音が鳴っている間停止してしまうため、8秒後,9秒後および10秒後に鳴らすBeep音のTaskを作成し、マルチスレッド処理をすることで、計測表示を維持させながら、Beep音を鳴らすように実装しました。
動作1と動作4でストップウォッチを開始させる際に、3つのTaskも開始させているのですが、動作3と動作7の際にストップウォッチ停止と合わせて3つのTaskをキャンセルさせる処理を実装したいです。
(実装しない場合、例えば8秒よりも前にフォームをクリック(2回目)の動作2を行うと、ストップウォッチが停止しているにも関わらず、Beep音が鳴ってしまうためです。)

発生している問題

CancellationTokenSourceを用いて、動作3と動作7にBeep音のTask3つを停止する処理を実装しようと試行錯誤したのですが、うまくいかずに躓いております。結果的に独学では行き詰まりを感じたため、質問を上げさせて頂きました。初歩的な内容かもしれませんが、言語を学習し始めて約2週間ということもあり、どうかお手柔らかにアドバイスを頂けますと幸いです。

何卒、よろしくお願いいたします。

該当のソースコードおよびエラー内容

C#

1public partial class Timer1 : Form 2 { 3 4 CancellationTokenSource tokenSource = new CancellationTokenSource(); 5 var token = tokenSource.Token; 6 7    private void timer_Tick1(object sender, EventArgs e) 8 { 9 labelTime.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 10 } 11 12 private async Task Beep8(CancellationToken token) 13 { 14 await Task.Delay(8000); 15 Console.Beep(); 16 } 17 18 private async Task Beep9(CancellationToken token) 19 { 20 await Task.Delay(9000); 21 Console.Beep(); 22 } 23 private async Task Sound(CancellationToken token) 24 { 25 await Task.Delay(10000); 26 Console.Beep(800,1000); 27 } 28 29 private void Timer1_Click(object sender, EventArgs e) 30 { 31 i++; 32 if (i == 1) 33 { 34 Console.Beep(); 35 sw.Restart(); 36 tick1.Enabled = true; 37 Task.Run(() => Beep8(token)); 38 Task.Run(() => Beep9(token)); 39 Task.Run(() => Sound(token)); 40 } 41 42 if (i == 2) 43 { 44 sw.Stop(); 45 tick1.Enabled = false; 46 tokenSource.Cancel(); 47 labelFtime1_1.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 48 labelTime.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 49 } 50 51 if (i == 3) 52 { 53 Console.Beep(); 54 sw.Restart(); 55 tick1.Enabled = true; 56 Task.Run(() => Beep8(token)); 57 Task.Run(() => Beep9(token)); 58 Task.Run(() => Sound(token)); 59 } 60 61 if (i == 4) 62 { 63 labelFtime1_2.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 64 } 65 66 if (i == 5) 67 { 68 sw.Stop(); 69 tick1.Enabled = false; 70 tokenSource.Cancel(); 71 labelGtime1.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 72 labelTime.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 73 } 74    75     //上記が1セットで、if (i == 25)の5セットの最後までは、ほぼ同じ内容の繰り返しのため割愛 76 }

エラー内容
CS0236:
フィールド初期化子は、静的でないフィールド、メソッド、またはプロパティ 'Timer1.tokenSource' を参照できません

CS0825:
コンテキスト キーワード 'var' は、ローカル変数宣言内またはスクリプトコード内でのみ有効です

補足情報(FW/ツールのバージョンなど)

・Windows 10 Home(64bit) Version 1903
・Microsoft Visual Studio Community 2019 Version 16.5.4
・.NET Framework4.7

TN8001👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

エラー原因

そこにvarは書けません。

他問題点

Task.Delay()CancellationTokenを渡さないと意味がないです。
CancellationTokenSourceは、キャンセル後は使いまわせないので作り直します。

cs

1using System; 2using System.Diagnostics; 3using System.Threading; 4using System.Threading.Tasks; 5using System.Windows.Forms; 6 7namespace Questions259056 8{ 9 public partial class Timer1 : Form 10 { 11 private readonly Stopwatch sw = new Stopwatch(); 12 private int i; 13 private CancellationTokenSource tokenSource; 14 15 public Form1() => InitializeComponent(); 16 17 private void timer_Tick1(object sender, EventArgs e) 18 => labelTime.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 19 20 private async Task Beep8(CancellationToken token) 21 { 22 await Task.Delay(8000, token); 23 Console.Beep(); 24 } 25 private async Task Beep9(CancellationToken token) 26 { 27 await Task.Delay(9000, token); 28 Console.Beep(); 29 } 30 private async Task Sound(CancellationToken token) 31 { 32 await Task.Delay(10000, token); 33 Console.Beep(800, 1000); 34 } 35 36 private void Timer1_Click(object sender, EventArgs e) 37 { 38 i++; 39 if(i == 1) 40 { 41 Console.Beep(); 42 sw.Restart(); 43 tick1.Enabled = true; 44 45 tokenSource = new CancellationTokenSource(); 46 var token = tokenSource.Token; 47 Task.Run(() => Beep8(token)); 48 Task.Run(() => Beep9(token)); 49 Task.Run(() => Sound(token)); 50 } 51 52 if(i == 2) 53 { 54 sw.Stop(); 55 tick1.Enabled = false; 56 tokenSource.Cancel(); 57 labelFtime1_1.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 58 labelTime.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 59 } 60 61 if(i == 3) 62 { 63 Console.Beep(); 64 sw.Restart(); 65 tick1.Enabled = true; 66 67 tokenSource = new CancellationTokenSource(); 68 var token = tokenSource.Token; 69 Task.Run(() => Beep8(token)); 70 Task.Run(() => Beep9(token)); 71 Task.Run(() => Sound(token)); 72 } 73 74 if(i == 4) 75 { 76 labelFtime1_2.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 77 } 78 79 if(i == 5) 80 { 81 sw.Stop(); 82 tick1.Enabled = false; 83 tokenSource.Cancel(); 84 labelGtime1.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 85 labelTime.Text = sw.Elapsed.ToString(@"mm\:ss.fff"); 86 } 87 } 88 } 89}

投稿2020/05/05 11:54

編集2023/07/21 12:59
TN8001

総合スコア9862

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

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

Mighty

2020/05/06 05:56

迅速かつ丁寧なご回答を頂き、誠にありがとうございます。 求める処理が実装できました。引き続き勉強頑張ります!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問