C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[9]: マルチスレッドについて教えてください。


(過去ログ 130 を表示中)

[トピック内 14 記事 (1 - 14 表示)]  << 0 >>

■77008 / inTopicNo.1)  マルチスレッドについて教えてください。
  
□投稿者/ ミーアキャット (15回)-(2015/09/04(Fri) 10:20:08)

分類:[.NET 全般] 

スレッドのテストプログラムを作ってみました。

目的はAsyncTest1()とAsyncTest2()を非同期に同時処理を
行うことです。
理由は
@AsyncTest1で3秒、AsyncTest2で4秒かかるとすると
通常だと7秒かかるので、タスク処理させると
AsyncTest2 の 4秒に近い処理で 2つの処理を
行うことができるという考えです。

そこで、以下のように作ってみました。
思うようにとりあえずは動作しました。

 public partial class Form1 : Form
 {
  bool flag1 = false;
  bool flag2 = false;

  public Form1()
  {
   InitializeComponent();
  }

  private void button1_Click(object sender, EventArgs e)
  {
   flag1 = flag2 = true;

   AsyncTest1();
   AsyncTest2();

   while(flag1 || flag2) Application.DoEvents(); ⇒A

   Console.Write("\r\n終了");
  }

  public async void AsyncTest1()
  {
   Random random = new System.Random();
   Console.Write("処理1開始\r\n");
   int result = random.Next(1000, 5000);
   await Task.Run(() =>
   {
    Thread.Sleep(result);
   });
   Console.Write("処理1終了:時間 {0}\r\n", result);
   flag1 = false;
  }

  public async void AsyncTest2()
  {
   Random random = new System.Random();
   Console.Write("処理2開始\r\n");
   int result = random.Next(1000, 5000);
   await Task.Run(() =>
   {
    Thread.Sleep(result);
   });
   Console.Write("処理2終了:時間 {0}\r\n", result);
   flag2 = false;
  }
 }

ここで、いくつか質問があります。

@目的のためのプログラムの作り方は間違っていないのでしょうか?

AApplication.DoEvents() の代わりに
何もできないようにしようと、Continue に変更すると
flag1, flag2 は変更されず無限ループになります。
AsyncTest1(), AsyncTest2() の終了待ちを行うのは
どうすればよいのでしょうか?

B実行先のPCが.net 4なので、Task.Run が
使え内容です。 .net 4ようにする場合

Random random = new System.Random();
const int N = 2;
Parallel.For(0, N, id =>
{
 if(id == 0)
 {
  Console.Write("処理1開始\r\n");
  int result = random.Next(1000, 5000);
  Thread.Sleep(result);
  Console.Write("処理1終了:時間 {0}\r\n", result);
 }
 else
 {
  Console.Write("処理2開始\r\n");
  int result = random.Next(1000, 5000);
  Thread.Sleep(result);
  Console.Write("処理2終了:時間 {0}\r\n", result);
 }
});

とすればよいのでしょうか?



引用返信 編集キー/
■77009 / inTopicNo.2)  Re[1]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (67回)-(2015/09/04(Fri) 11:13:02)
全体をawaitする形にするのが普通な気がします。
引用返信 編集キー/
■77010 / inTopicNo.3)  Re[2]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (68回)-(2015/09/04(Fri) 11:43:26)
例えばですが、今の例だと、AsyncTest1とAsyncTest2の戻り値をTaskに書き換えて(void→Taskと書き換えるだけ)、呼び出し側ではそれぞれawaitします。

意味的には個別にawaitではなくて、
Task.WhenAll(AsyncTest1(), AsyncTest2());
の方がいいですね多分。

引用返信 編集キー/
■77011 / inTopicNo.4)  Re[3]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (70回)-(2015/09/04(Fri) 11:45:29)
No77010 (なちゃ さん) に返信
> 意味的には個別にawaitではなくて、
> Task.WhenAll(AsyncTest1(), AsyncTest2());
> の方がいいですね多分。

呼び出し側では、
await Task.WhenAll(AsyncTest1(), AsyncTest2());
みたいにするってことです。
引用返信 編集キー/
■77013 / inTopicNo.5)  Re[4]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (71回)-(2015/09/04(Fri) 12:24:19)
画面を触れないようにするには、タスク呼び出し前に例えばフォームのEnabledをFalseにして、全体のawait後にTrueに戻すなどの方法があります。
まあこれをするとフォーム全体が操作不能になるので、本当はもう少し細かく制御する方がいいですが。

引用返信 編集キー/
■77014 / inTopicNo.6)  Re[5]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (72回)-(2015/09/04(Fri) 12:33:32)
.NET Framework 4の場合は…
Taskはまあ明示的に作ればすむ話ですが、awaitが使えないのが非常に面倒です。
引用返信 編集キー/
■77015 / inTopicNo.7)  Re[2]: マルチスレッドについて教えてください。
□投稿者/ ミーアキャット (16回)-(2015/09/04(Fri) 12:47:04)
No77009 (なちゃ さん) に返信
> 全体をawaitする形にするのが普通な気がします。

  bool flag = false;
  private void button3_Click(object sender, EventArgs e)
  {
   flag = true;

   AsyncTest3();

   while(flag) Application.DoEvents();
  }

  public async void AsyncTest3()
  {
   Random random = new System.Random();
   Console.Write("処理1開始\r\n");
   int result1 = random.Next(1000, 5000);
   int result2 = random.Next(1000, 5000);
   await Task.Run(() =>
   {
    Thread.Sleep(result1);
    Thread.Sleep(result2);
   });
   Console.Write("処理終了:時間 {0} {1}\r\n", result1, result2);
   flag = false;
  }

まとめましたが
これだと、シングル処理となんら変わりませんでした。
処理に result1 + result2 の時間がかかりました。
「全体をawaitする形」の意味がちがうのでしょうか?

引用返信 編集キー/
■77016 / inTopicNo.8)  Re[3]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (74回)-(2015/09/04(Fri) 12:57:12)
> まとめましたが
> これだと、シングル処理となんら変わりませんでした。
> 処理に result1 + result2 の時間がかかりました。
> 「全体をawaitする形」の意味がちがうのでしょうか?

意味が違います。
一例ですがそれ以降の書き込みの具体的な例を見てください。

引用返信 編集キー/
■77017 / inTopicNo.9)  Re[4]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (75回)-(2015/09/04(Fri) 13:22:40)
各タスク内でそれぞれawaitする必要がなければ、普通にWhenAllでawaitするだけです。
引用返信 編集キー/
■77018 / inTopicNo.10)  Re[5]: マルチスレッドについて教えてください。
□投稿者/ ミーアキャット (18回)-(2015/09/04(Fri) 13:58:29)
No77017 (なちゃ さん) に返信
> 各タスク内でそれぞれawaitする必要がなければ、普通にWhenAllでawaitするだけです。

すみません。いろいろ試しましたが
書き方がわかりません。

Task.WhenAll(AsyncTest1(), AsyncTest2());
この時点で「最も適しているオーバーロード メソッドには無効な引数がいくつか含まれています。」
となってしまいます。
引用返信 編集キー/
■77019 / inTopicNo.11)  Re[6]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (76回)-(2015/09/04(Fri) 15:52:04)
No77018 (ミーアキャット さん) に返信
> ■No77017 (なちゃ さん) に返信
>>各タスク内でそれぞれawaitする必要がなければ、普通にWhenAllでawaitするだけです。

普通にというのは、Taskを普通にWhenAllでawaitするという意味です。
Task.WhenAll(Task.Run(…), Task.Run(…));
みたいに。

今のようなメソッドの構造のままにしたいなら、AsyncTest1などの戻り値をTaskにする必要があります。
メソッド内でawaitするならvoidをTaskに書き換えるだけ、awaitしないならTask.Run()などの戻り値をそのままリターンする感じになります。


引用返信 編集キー/
■77020 / inTopicNo.12)  Re[7]: マルチスレッドについて教えてください。
□投稿者/ なちゃ (77回)-(2015/09/04(Fri) 15:54:49)
> 普通にというのは、Taskを普通にWhenAllでawaitするという意味です。
> Task.WhenAll(Task.Run(…), Task.Run(…));
> みたいに。

おっと、awaitを入れて書いたら
await Task.WhenAll(Task.Run(…), Task.Run(…));
のような感じです。
引用返信 編集キー/
■77022 / inTopicNo.13)  Re[8]: マルチスレッドについて教えてください。
□投稿者/ kiku (59回)-(2015/09/04(Fri) 18:26:29)
勉強しながら始めてasync/await使ってみました。
質問者さんの意図に合っていないかもしれませんが、
自身の意図通りには一応動いています。
参考になればいいですが・・・

        private async void button1_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Debug.Print("button1開始");
            button1.Enabled = false;
            var task1 = work1();
            var task2 = work2();
            var task3 = work3();
            System.Diagnostics.Debug.Print("button1終了");
            await Task.WhenAll(task1, task2, task3);
            button1.Enabled = true;
            System.Diagnostics.Debug.Print("全仕事終了");
        }

        public async Task work1()
        {
            System.Diagnostics.Debug.Print("仕事1開始");
            await Task.Run(() => Thread.Sleep(5000));
            System.Diagnostics.Debug.Print("仕事1終了");
        }

        public async Task work2()
        {
            System.Diagnostics.Debug.Print("仕事2開始");
            await Task.Run(() => Thread.Sleep(3000));
            System.Diagnostics.Debug.Print("仕事2終了");
        }

        public async Task work3()
        {
            System.Diagnostics.Debug.Print("仕事3開始");
            await Task.Run(() => Thread.Sleep(1000));
            System.Diagnostics.Debug.Print("仕事3終了");
        }

引用返信 編集キー/
■77055 / inTopicNo.14)  Re[9]: マルチスレッドについて教えてください。
□投稿者/ ミーアキャット (19回)-(2015/09/08(Tue) 10:40:52)
なちゃさん、kiku さん
どうもありがとうございました。

理解できました。

ただ、やはり、.net4では動作しないので
Thread を使って作ります。

自分のPDで動作させるときには
使いたいと思います。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -