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

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

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

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

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

3回答

1494閲覧

【C#WPF】ボタンが押されたら処理をやり直したい

nura_nura

総合スコア15

C#

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

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

1クリップ

投稿2017/09/29 06:22

###前提・実現したいこと
ボタンA,Bがあり、ボタンAを押した後に関数Aが実行され関数Aの処理が終わらない内にボタンBを押すと関数Bが実行され、関数Aと関数Bが並列に実行されるため処理が変になります。
ボタンを押したら今の処理を終わって新しく処理を開始したいです。
グローバル変数で管理しようと思ったのですが関数内にfor文が幾つかあり、いちいちフラグ管理を入れると長くなるのでもっとスマートに出来たら嬉しいのですが、何かいい方法がありませんか。

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

C#

1 //ボタンAが押された時 2 private async void funcA() { 3 for(int i =0;i<50;i++) { 4 //処理A 5  Slider.Value = i; 6  await Task.Delay(50); 7 } 8} 9 10//ボタンBが押された時 11private async void funcB() { 12 for(int i =50;i>0;i--) { 13 //処理B 14  Slider.Value = i; 15  await Task.Delay(50); 16 } 17} 18 19//何かしらのボタンが押された時 20 private void Buttons_Clicked(object sender, RoutedEventArgs e) 21 { 22 String btnName = ((Button)sender).Name.Replace("Button", ""); 23 switch (btnName) 24 { 25 case "A": //ボタンAが押された 26 funcA(); 27 break; 28 case "B": //ボタンBが押された 29 funcB(); 30 break; 31 } 32 }

関数はイメージです。徐々にスライドバーを動かすような処理をしています。実際は複数のスライドバーを順番に動かしているためfor文が幾つかあります。

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

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

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

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

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

guest

回答3

0

キャンセルトークンの出番では?

投稿2017/09/29 06:40

kiichi54321

総合スコア1984

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

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

nura_nura

2017/09/29 08:05

回答ありがとうございます。 調べてみたのですが、クリックイベント(Buttons_Clicked)関数内でキャンセルするということでしょうか。 CancellationTokenSourceとCancellationTokenをグローバルにして処理自体は関数のまま置いときたいのでTask.Run(()=>funcA(),token);などしてクリックイベントの最初でトークンソースをキャンセルしてみたのですが上手くいきませんでした。 初心者なもので具体的な処理方法教えていただけると助かります。
kiichi54321

2017/09/29 15:19 編集

まず、「一度に処理をやり直したい」というのを考えるのをやめて、「適切に終了する」「再開する」ということに問題を分けます。 適切に終了するために、CancellationToken の ThrowIfCancellationRequested で例外を引き起こすことで、Taskを終了させます。 これは、ややこしいフラグ管理をしないために使います。 そして、すべてのTaskの終了を検知するために、Task.WaitAll をつかます。 これを使うためにも、すべてのTaskを、コレクションで、プライベートフィールドに持つようにします。 Task.WaitAllを待ってから、また、TaskとCancellationTokenを再作成をすれば、再開ができると思います。 ただ、これは、典型的な難易度の高いマルチスレッドプログラミングになるので、初心者であるという自覚があるなら、問題をもっと簡単にしたほうがいいと思います。 (ちなみに、C#には、グローバルという概念は、一応ありません。staticかな。とはいえ、staticを使う話でもありません。)
nura_nura

2017/10/02 02:36

返信ありがとうございます。 色々調べてみましたが難しいようですので今回は諦めます。
guest

0

自己解決

お二方の回答ありがとうございました。
私の力不足のため解決に至らず申し訳ありません。
同じボタンの二度押しの対応は諦めました。
根本的な解決にはなってませんがスライダーの値を直接変える処理がfor文で沢山あっただけなので一つ関数をかませて無理やりしました。

C#

1 2int currentMotion = -1; 3//ボタンAが押された時 4 private async void funcA() { 5 int motion = 1; 6 for(int i =0;i<50;i++) { 7 //処理A 8  setSliderValue(i, motion); 9  await Task.Delay(50); 10 } 11} 12 13//ボタンBが押された時 14private async void funcB() { 15 int motion = 2; 16 for(int i =50;i>0;i--) { 17 //処理B 18  setSliderValue(i, motion); 19  await Task.Delay(50); 20 } 21} 22 23// スライダーに値を送る 24void setSliderValue(int value, int motion) { 25 if(motion != currentMotion) 26 return; 27 Slider.Value = value; 28} 29 30//何かしらのボタンが押された時 31 private void Buttons_Clicked(object sender, RoutedEventArgs e) 32{ 33 String btnName = ((Button)sender).Name.Replace("Button", ""); 34 switch (btnName) 35 { 36 case "A": //ボタンAが押された 37 currentMotion = 1; 38   funcA(); 39 break; 40 case "B": //ボタンBが押された 41 currentMotion = 2; 42 funcB(); 43 break; 44 } 45}

投稿2017/10/02 02:48

nura_nura

総合スコア15

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

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

0

細かいタイミングまで気にしないで良いなら、画面ロックかボタンを使用不可とすれば良いんじゃないでしょうか。

投稿2017/09/29 07:11

sazi

総合スコア25188

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

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

nura_nura

2017/09/29 08:07

回答ありがとうございます。 すみません、ボタン二重クリックで再実行されるようにしたいです。
sazi

2017/09/29 08:47

>二重クリックで再実行 とは、実行中の処理をキャンセルして再度実行するということですか? そもそも、二重クリックとはダブルクリックのことでは無いですよね? C#は詳しくないですが、実行中をキャンセルするとかであればスレッドでの管理が必要じゃないのでしょうか それよりも、「実行中に別の処理をされたらおかしくなる」というのを抑制する方が先ではないですか
nura_nura

2017/10/02 02:36

返信ありがとうございます。 はい、二重クリックは2度押しの事です。 ボタン2度押しで二つのスレッドが同時に1つのスライドバーを動かすことになるので処理がおかしくなるのは仕方がないです。 難しそうなので諦めます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問