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

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

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

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

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

4回答

9227閲覧

【.NET】マルチスレッドプログラミングの学習

syogakusya

総合スコア67

C#

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

マルチスレッド

マルチスレッドは、どのように機能がコンピュータによって実行したのかを、(一般的にはスレッドとして参照される)実行の複合的な共同作用するストリームへ区分することが出来ます。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

0グッド

0クリップ

投稿2016/08/31 04:22

##質問
.NETにおけるマルチスレッドプログラミングの学習をしたいため、参考になるサイト・書籍を教えていただきたいです。

##背景
業務によりしばしばマルチスレッドのサーバーサイドアプリケーションを開発するのですが、社内では未だにスレッド関連の機能の実現にSystem.Threading.Threadクラスを利用しています。
ところが、ネット上では「ThreadクラスのTaskクラスによって完全に取って代わられるべきである」といった趣旨の文献が多数散見されます。
とはいえ、実際にTaskクラスを利用してみたところ、特定のスレッドで負荷がかかる処理を行うとそのスレッドが止まってしまう、といった問題が発生したことがありました。(そして、その問題はTaskクラスをThreadクラスに置き換えることで解決しました。)
このような事情から業務では未だにThreadクラスを利用しているのですが、これからもThreadクラスを使い続けることに危機感を覚えています。
そこで、.NETの並列処理に関する技術を体系的に学習し、今後の業務に生かしたいと思いました。

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

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

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

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

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

guest

回答4

0

基本的には、TaskクラスがThreadクラスに劣るような部分はないので「ThreadクラスのTaskクラスによって完全に取って代わられるべきである」の考え方は正しいと思います。

実際にTaskクラスを利用してみたところ、特定のスレッドで負荷がかかる処理を行うとそのスレッドが止まってしまう、といった問題が発生したことがありました。

これは、Taskクラスがスレッドプールを基盤にしているので、ワーカースレッドの最大数以上の処理をTaskクラスに同時に処理させようとしたから発生している問題では?
だとすれば、Taskクラスのワーカースレッドの最大数の設定を適切に増やしさえすれば解決する問題のはずです。

ちなみに、私は最近になってC#を本格的に使用するようになったのですが、非同期メソッド入門 (1) - 非同期処理の歴史の記事が、最初にC#における非同期処理(マルチスレッドに留まらない非同期処理全般)の全体像を知るうえで非常に参考になりました。

投稿2016/08/31 04:44

KenjiToriumi

総合スコア344

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

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

syogakusya

2016/08/31 11:09

ありがとうございます。当該の記事を参考にさせていただきます。 仰っていることがほぼ分からない現状を鑑みるに、やはり.NETの並列処理関連の技術について全く知識が足りていないのだと再認識しました。 まずは皆様にいただいた情報源をもとに、腰を据えて知識をつけていこうと思います。
KenjiToriumi

2016/08/31 12:53

ご質問内容は「マルチスレッドプログラミング」という事ですが、本当に必要としているのは「マルチスレッド」なのか「非同期処理プログラミング」なのかも一度考えてみるとよいと思います。 UWPでは、非同期処理プログラミンが基本となりますが、この時マルチスレッドではなく、async/awai を使用した非同期処理が基本となりますしね。 また、本当にパフォーマンスが必要となるプログラムになる場合も、マルチスレッドではなくOSの提供する非同期処理をダイレクトに扱うような非同期処理機構を使用すべきですので、「マルチスレッドではない非同期処理プログラミング」についての情報も仕入れておくことをお勧めします。
guest

0

薦めていただいた書籍「C#によるマルチコアのための非同期/並列処理プログラミング」が手に入りました。
書籍なので当然といえば当然ですが、情報リソースとしてのボリュームが最も大きいので、これを薦めてくださった方をベストアンサーとさせていただきます。
これからじっくり読んでいきます。
ありがとうございました。

投稿2016/09/03 12:38

syogakusya

総合スコア67

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

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

0

「ThreadクラスのTaskクラスによって完全に取って代わられるべきである」

それは間違った認識です。Taskクラスは完璧ではありません。状況に応じて使い分けるべきです。

例えば、BackgroundWorkerクラスは有力な選択肢となり得ます。進捗を通知する仕組みを備えているので、「ダウンロード中 ○○%」のような表示をさせたいときなどに便利です。

また、時間のかかる処理やスレッドの優先度を変更する場合など、スレッドプールを使うべきではない場合もあります。
その辺のことは、マイクロソフトもスレッドプールを使わない方が良い場合があると説明しています。参考にしてみてはいかがでしょうか。
The Managed Thread Pool


追記
説明不足でした。前述の「時間のかかる処理」とは、その都度スレッドを走らせるのではなく、例えばサーバーの要求待ちタスクのような一定期間裏で動き続けているような処理のことです。

投稿2016/08/31 10:39

編集2016/08/31 10:53
catsforepaw

総合スコア5938

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

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

syogakusya

2016/08/31 11:51 編集

ご回答ありがとうございます。 当該の記事を参考にさせていただきました。 追記されたことに関して、宜しければ教えていただきたいのですが、スレッドプールを使うべきでない場合はどのようなコンポーネントを利用して並列処理を実現すればよいのでしょうか。 実は、キューの処理や疎通の監視など、そういった「サービス内の終わりのない処理」に関しても、ThreadクラスではなくTaskクラスを使うべきなのかということは、私が最も知りたかったことの一つでした。 というのも、Taskクラスを利用するサンプルソースはいくつか見たことがありますが、どれも「時間はかかるが終わりのある処理」を行うためのもので、サービスのOnStartイベントで立ち上げてOnStopイベントで落とすようなスレッド処理の実現に使っているサンプルは見たことがありません。 とはいえ、いかなる理由があってもThreadクラスは使うな、といった記事がやはり多いので、そこのところを以前に検索エンジンで調べてはみたのですが、参考になる情報が見つかりませんでした。 追記: 申し訳ございません。 加えてもう一つご意見をお聞かせいただきたいことがあるのですが、件の「その都度スレッドを走らせるのではなく、例えばサーバーの要求待ちタスクのような一定期間裏で動き続けているような処理」「サービスのOnStartイベントで立ち上げてOnStopイベントで落とすようなスレッド処理」につきまして、このような処理を行う場合、Taskクラスは使ってはならないと言えますでしょうか。 それとも、ケースバイケースなのでしょうか。
catsforepaw

2016/08/31 12:28

> スレッドプールを使うべきでない場合はどのようなコンポーネントを利用して並列処理を実現すればよいのでしょうか。 普通に`Thread`クラスを使えば良いかと思います。 > サービスのOnStartイベントで立ち上げてOnStopイベントで落とすようなスレッド処理の実現 状況にもよりますが、そのようなタスクを何本も走らせる場合は、私なら`Thread`クラスを使います。そもそもスレッドプールを使う理由はスレッドの生成/破棄にかかるコストを節約するためですが、そのコストが無視できる場合は、「無駄なスレッドプールの消費」を避けた方が得策の場合もあります。スレッドプールの管理コストも莫迦にはなりませんから。 それに、そのようなタスクの場合、スレッドの優先度も設定した方が良い場合もありますし。 > いかなる理由があってもThreadクラスは使うな、といった記事がやはり多いので、 そんな記事は無視してもかまいません。考えることを放棄してはいけません。
catsforepaw

2016/08/31 12:35

追記された件ついて > それとも、ケースバイケースなのでしょうか。 ケースバイケースです。Taskクラスは直感的なコーディングができますから、見た目の判りやすさという点でTaskクラスを選択することもありだと思います。その場合は、必要に応じてスレッドプールの下限値を底上げするなどの対処が必要ですが。 要するに、「何も考えずにとにかくTaskを使え」というは問題外で、ちゃんと仕組みを理解した上で、最初に書いた通り状況に応じて使い分けるべきだということです。
guest

0

ベストアンサー

Webサイトは「C# によるプログラミング入門 | ++C++; // 未確認飛行 C」と「Threading in C#(英語)」を、書籍は「C#によるマルチコアのための非同期/並列処理プログラミング」をお薦めしておきます。

ただし、スレッド利用が適切とも限らないケースも多々ありますからご注意ください。


ネット上では「ThreadクラスのTaskクラスによって完全に取って代わられるべきである」といった趣旨の文献が多数散見されます。

これは概ね正しい主張だと思います。ただしThreadを単純にTaskへと置き換えれば良いという話ではありません。現実的にはユースケースに応じて、Taskやasync/awaitを組み合わせていくべきですね。

投稿2016/08/31 04:34

編集2016/08/31 04:43
yohhoy

総合スコア6189

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

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

syogakusya

2016/08/31 10:59

ご回答ありがとうございます。 サイト・書籍ともに活用させていただきます。 スレッド利用が悪い考えである…というのは、例えばクライアントから受け取ったデータをキューにためて、それを順次処理をしていくような2スレッドのサーバーサイドアプリケーションを想定した場合、これを2つのアプリケーションに分割するようなことを意味するのでしょうか? 本題から逸れますが、このような具体例でどのようにしてシングルスレッドで実現するのかご意見をいただければ幸いです。
yohhoy

2016/08/31 13:42 編集

アプリケーションが「スレッドを利用することが悪い考え」ではなく、「プログラマが直接スレッドを制御するようなコーディングは悪い考え」と解釈ください。 スレッドを直接制御することは、本来アプリケーションが果たすべき目的ではなく、実装の手段にすぎません。また、マルチスレッドによる並行/非同期プログラミングは本質的な難しさを抱えており、不慣れなプログラマが作成したマルチスレッド・アプリケーションは悪夢のようなバグの温床にしかなりません。スレッドという機構は並行/非同期プログラミングにおける低レイヤな部品に過ぎません。アプリケーションプログラマの注意をより本質的な問題にフォーカスするため、可能な限りTaskやasync/awaitのような高レイヤの部品を用いるべきです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問