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

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

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

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

Q&A

7回答

7754閲覧

C#でスレッドを使う場合

PorkCutlet

総合スコア26

C#

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

8グッド

11クリップ

投稿2017/07/05 01:46

C#でスレッドを使う場合「Threadはもう古い、時代はTaskや!」みたいなサイトをよく見かけますが、単純に処理を行う1スレッドを起こす場合もTaskの方が優れているのですか?

例えばメインスレッドはUIを処理するとして、起動中ずっとバックグラウンドで処理を行いたい場合など。
Treadは起動時の作成時のコストが重い等書かれていますが、1度起動してそのままずっと居座って処理を続けるような場合においてもTaskが用意しているスレッドプールの機構よりも重いんでしょうか?

Taskを盲信しているように見えてしまいます。あとあまり触れられないBackgroundWorkerは…

i50, BeatStar, oriduru, nullbot, twyujiro15, s8_chu, yohhoy, KSwordOfHaste👍を押しています

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

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

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

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

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

guest

回答7

0

Taskの目的は性能向上ではなく利便性の向上です。

ThreadPoolがあれば改善するのは速度ではなく、「スレッドの上限を超えてしまう問題」や「スレッド数を制限する」とかそうした煩雑さとの決別にあります。
非同期プロシージャコールを考えるより、Taskとして積み上げてしまった方が簡単です。
async-awaitプログラミングには必要不可欠だったし、わずか10行のコードを書いてサブスレッドで実行させるなんてのに毎回難しいことはしたくない。
IOバウンドな非同期タスクの実装の簡易化はThreadからの進化の最良の例といえるでしょう。
Threadインスタンスを直接保持しないというのも利点です。

Taskの利便性向上が目的ということの証左に、Taskは例外も拿捕しやすくなっています。
Thread内で起きる例外をメインアプリケーション側でフックするのは比較的難しい行為です。
しかし、TaskはAggregateExceptionで呼び元に返してくれることや、UnhandledExceptionもAppDomainよりも内側で返してくれます。
Taskの進化はThreadで実装しようと思った時に高度に要求された内容を咀嚼したものです。

C#は最新技術を搭載しようぜ!でも使う方はよくわかんなくてもいいようにしたいね、みたいな風変りな圧力が掛かった言語だと思います。
そういったフランクさがC#の良いところだと思います。
殆どの言語が新しい概念をデフォルトで使えるように進化しているので、それは時流といえば時流ですし、
古いコードはどんどんobsoleteになってしまったり新しい概念と衝突したりといった問題も抱えているので、良いところばかりとは言えないんでしょうけどね。

TaskはThreadをより高水準化した再実装なのです。
よりネイティブな方が早そうじゃん、って言われても、測って、とか、突き詰めればそれはそうでしょうね、としか言えません。
正に、C++とC#の違いですよ。Threadと、Taskっていうのは。

#追記

再実装という言い回しには誤りがあったので訂正します。
ソースを提示するのが一番適切な回答であると判断に至り、追記させて頂きます。

Task自身は実行に関するロジックを持っておらず、該当箇所はThreadPoolTaskScheduler内にあります。
Taskの実行にあたりTaskScheduler.Currentが呼び出されます。
ThreadPoolTaskSchedulerはTaskSchedulerクラスのデフォルト実装です。

https://referencesource.microsoft.com/#mscorlib/system/threading/Tasks/ThreadPoolTaskScheduler.cs

最終的にはLongRunningのオプションの有無によってThreadか、ThreadPoolにTaskを振り分ける実装であり、動作速度自体はラップの有無程度になると思います。
実行ソースはシンプルなので、ThreadとTaskの距離感も分かりやすいのではないでしょうか。

C#

1 protected internal override void QueueTask(Task task) 2 { 3 if ((task.Options & TaskCreationOptions.LongRunning) != 0) 4 { 5 // Run LongRunning tasks on their own dedicated thread. 6 Thread thread = new Thread(s_longRunningThreadWork); 7 thread.IsBackground = true; // Keep this thread from blocking process shutdown 8 thread.Start(task); 9 } 10 else 11 { 12 // Normal handling for non-LongRunning tasks. 13 bool forceToGlobalQueue = ((task.Options & TaskCreationOptions.PreferFairness) != 0); 14 ThreadPool.UnsafeQueueCustomWorkItem(task, forceToGlobalQueue); 15 } 16 }

Threadクラス自体の細かい情報が必要で、自身による拡張の特殊性がMS製のTaskを上回るならThreadを使う判断は有りだ、と考えてよいと思います。

投稿2017/07/05 04:25

編集2017/07/11 04:53
haru666

総合スコア1591

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

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

PorkCutlet

2017/07/05 06:10

スレッドプールを使いたいとか 小さい処理をタスクとして実行したいとか 上記のようなことをするのに旧来のThreadクラスを用いると、コスト(処理コストだけにあらず、実装コストなども含め)が高くなるのはわかります。 そうではなく、単純にメインループをもう1個作りたいようなときにTaskクラスを用いると、逆に手がかかるような気がします。 Taskクラスはスレッドの使いかたの1つのパターンを実装したのもので、すべてのスレッド処理を置き換えるものでは無いように思えます。(いわゆる銀の弾などない) >正に、C++とC#の違いですよ。Threadと、Taskっていうのは。 C++(Visual C++)にも並列パターン ライブラリとかでTaskもどきが使えますが… C++が古いまま進化していない言語だと思っておられます? C++も「殆どの言語が新しい概念をデフォルトで使えるように進化」の対象だと思いますが。C#ほどの勢いはないかもしれませんが。
haru666

2017/07/05 06:42

>>単純にメインループをもう1個作りたいようなときに 多分根本的な実装方法が違うんだと思います。 私はまずメインループをもう1個作ろうなんてことに基本的にはなりません。 C#でサーバー類を作る時も、メインスレッドは最終的にConsole.ReadKey(ないしそれに相当するもの)して終わりです。 後はリスナー類にごちゃごちゃと非同期なタスクのハンドラをバインドしていくようにコーディングします。 この処理は重たいなー、個別にスケーリングしたいなーと思ったらアプリケーションを分けます。 雑だけど原始的で簡単な方法だと思っています。 私にもPorkCutletさんの作りたいものの具体像が見えていないので、「Task流の組み方があるかもしれないし、ないかもしれない」、「Threadをそのまま使った方が良いかもしれない」これは分からないところです。 基本的にはTask流の組み方があるものと思っています。 Threadで実装できるものはTaskで実装できるし、Taskで実装できるものはThreadで実装できるものが殆どで、その実行コスト差も許容できないほどのものではないだろうと思います。 そういう意味じゃ、ReplacableはReplacableだろうと思いますよ。 銀の弾丸のような「これで全てすぐ解決」って話じゃあなくね。 今作ってるものを再実装するとなると余剰コストの回収には見合わないかもしれませんが、新しいものを作る時において「Threadの方が良かった」は少ないだろうと思います。 >>C++が古いまま進化していない言語だと 一応C++の新版が出る度チェックはしています。 C++とC#を当初の、と書くかは迷ったところなのですが、C#がC++より高水準言語であるというのは今のところ覆ってはいないと思うんですよね。 なのでこのような表現をしました。 ダイナミックな文法の省略とかはC++でもまだまだできない部分もありますから、それでいいかなと。 Threadは今後の進化をあまり見込めないため、C++とC#の図式はより近くなってくことを考えれば、今しか通用しない表現かもしれませんけどね。 結構このあたりは難しくて、単純な実装だとC++よりC#が早いようなケースもでてきています。 それだけ処理方式より、技術の進歩によって実装依存の世界に入ってきていると思います。 ので、この話は書き味としての高水準さだけを見て頂きたいところですね。
PorkCutlet

2017/07/05 07:29

やりたいことは、本当にただ処理をするスレッドを作りたいだけでタスクのスケジューリングとかは不要ですし、例外のハンドリングも含め処理スレッド側で完結させるので、管理側がすることは開始要求・停止要求程度でいいのです。 (正体はWindowsサービスです。ただしサービス以外でも起動させたいので、管理側と処理スレッド側は最低限のインターフェースで繋がっていて、双方相手が何者かわからないまま動作することが望ましいのです。) プロセスを分けてしまえ!というのもありですが、それはそれでプロセス間通信を考えないといけなくなるので面倒なのです。 Taskを選んでもメリットがないなぁ、それどころかTaskの仕様に縛られるなぁ。 でも世の中Task!Task!Threadはもう古い!って書かれているので、Taskで書いた方がいいのかなぁ。 ということで、この質問なのです。
haru666

2017/07/05 08:18

これは、割り切りの問題だと思います。 僕は実現すること自体尊いことだと思いますし、あれならもうThreadで作ってしまうべきです。 Taskの方が仮に100%、全てにおいて優れていようと、別にThreadを使ってはいけない理由にはなりません。 用途が限定されていてもう設計が出来ており、それがThreadに最適化されているならどちらで作っても大差ないでしょう。 今までの経験と比較して発生する相対的な学習コスト差は計上すべきコストですから。 特に未経験ではイメージの問題でTaskで作った方が高くつく場合は当然あるでしょう。 ある特定の場合Threadの方が有利でしょ、ってな質問に私はYESと結論を持っていけません。 TaskはThreadのアップグレード版であること、並びに、そこで比較されるThread使用時のコストと、Task上での実行コストを、私は無視して良いコスト差だと考えているからです。 ThreadではTaskっぽいコードは書けませんが、TaskではThreadっぽいコードは十分書くことができます。 Taskを一生活かしておいて、同じような処理を実装すればThreadと大差ありません。 しかし、それで「Taskらしい形になったのか」と言われればこれには疑問符をつけざるを得ないのは共通の理解が得られるところだと思います。 Task流のやり方で利点を生み出せるまで勉強するかどうかは貴方次第です。
kiichi54321

2017/07/05 16:07

回答にも書いたけど、ちゃんとこの記事を読むといいと思うなぁ。 http://engineering.grani.jp/entry/2017/06/02/190012 今、CMをガンガンやっているスマホゲームのサーバー側の実装で、意図的にTaskではなくThreadを使っていて、その理由を書いてあるのだから。PorkCutletさんの考えていることを補強するものになってますよ。
haru666

2017/07/06 01:52 編集

kiichiさん、Graniのゲームの場合は微少なコスト差も無視できない場合です。 そしてTask、Thread双方に対する深い理解があります。 完全にThread向きの処理で、設計上そうならざるを得ず、それができるだけの技術があれば満足してThreadを使えるでしょう。 Taskは全体最適を目指した横方向の進化で、部分最適に一致するとは限りません。 ですから、 ・PorkCutletさんの詳細な要件が分からないので、どちらの方が良いとまでは言えない ・多くの場合私はTaskの進化の余剰コストを無視できる程度であると考えている と注意しているつもりです。 「Taskの方がやっぱりよかったんじゃないか?」を払拭できるほどの情報はこの場では出せません。 スレッドがCPUバウンドで100%消費しつづけられる長期的な一枚岩である場合は、Threadで良いだろうな、ぐらいのうっすらとした理解は私にもあります。 (突き詰めたことがないので、どこまで突き詰めればそうなるのかはわかりません。)
haru666

2017/07/06 02:08 編集

もしも「Threadの方が良い場合があるのか」だけが質問という意味でも それについては、「ある」と答えているつもりです。 「PorkCutletさんのやり方がそうとまではわからない」が余計って意味でしょうかね。 「突き詰めればそうでしょうね」に突き詰まらない人の方が多いように考えているので、「Threadが古い」と言われても仕方ないと思っています。 追記:TaskのLongRunningとThreadの違いは、処理を行うという以外の部分でどちらが必要かという話になるので、Granniが彼らの需要でThreadを選んだからといってThread良しとなるとまでは言えないと思います。
haru666

2017/07/06 03:06 編集

うーん、簡単なリサーチをしてきました。 明確なThreadを使うべきとき、を例示してくれたのは下記の2番目のレスです。 https://stackoverflow.com/questions/13429129/task-vs-thread-differences 要約すると、Long-Running なタスクでかつ ・スレッドに名前を付けたい時=個別に管理したい時 ・スレッド別にステートを管理したい時(ThreadLocalのようなもの) ・the apartment state(to show a UI) を決定したい時(意味がよくわかりませんでした) という感じでした。 最後のはTaskがデフォルトMTAなのでSTAに変えたい場合、という意味かもしれませんが、(to show a UI)の意味がちょっとわかりませんでした。 そこでも概ねTaskがベストなことが多いって結論は変わりませんが…。 また、上記スレでも一番評価が高かった回答は「Threadはローレベル、Taskは名前通りタスクを高レベルで抽象化したもの」といったような内容のものです。 他の記事もいくつか読んでみましたが、クラス自体にフォーカスした情報はなかなか見つけられません。 どのように非同期処理を組むべきか、というマナーとは少しズレた話題なので、「TaskでもLong-Runningオプションあるぜ」ぐらいの回答が多いように思います。
guest

0

少数の固定的な仕事を行うThreadを完全に制御したいならThreadでかまわないと思うのですが、単にそのようなスレッド制御を書くより、その時々で並列に処理したい小さな処理断片をスレッドプールへ「よきにはからっておいてください」というスタイルの方が簡単なことが多いというだけの話であると思います。

真っ当なThreadを使うとすると「どのアプリケーションでもにたような制御を毎回書くのがめんどくさい」からこそTaskを使うということだと思います。

「その時々で並列に処理したい小さな処理断片を一々Threadを起こして実行する」といったことに比べれば明らかにTask(スレッドプール)を使うことの方が優れていると思います。

しかしライフサイクルが長く、並列に行いたい処理がスレッド毎に明確に設計されているならThreadで一向にかまわないと思います。例がよくないですが、例えばガベージコレクションを一定時間ごとに自律的に行ってくれるスレッド・・・といったものですとThreadプールに細切れで処理を投げるのではなく専用のThreadを起動する方が適切ではないでしょうか?

投稿2017/07/05 02:06

編集2017/07/05 03:00
KSwordOfHaste

総合スコア18394

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

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

0

こんにちは。

Taskはコンソール・アプリだとawaitの前後でスレッドが切り替わるので落とし穴に嵌りそうです。awaitの前後でThreadLocalのインスタンスが異なるとか、なかなか恐怖です。

TaskはGUIとの連携を素直に記述できるので優れていると思いますが、非GUI環境ではあまり意味がないし、デメリットもある仕組みです。
デメリットを考慮せず、盲目的に特定の仕組みを推奨する人は「アマチュア」なので、話半分に聞いておいた方がよいかも知れません。

投稿2017/07/05 02:29

Chironian

総合スコア23272

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

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

haru666

2017/07/05 02:43

僕はーThreadLocalを使うこと自体が悪だと思いますね… Task全盛期の今、ThreadLocalはグローバル領域の汚染でございますし、嫌でございます。。。 1人で仕事するんならOKですが、複数人で作業する場合、Thread Bindingな処理を書くというのは御し難いと思うんですが。
Chironian

2017/07/05 02:52 編集

私はグローバル変数は悪とは思いません。安易に使うべきではないですが、必要な場合は使うべき仕組みと思います。スレッド・ローカルも同様です。 無理して使わない場合、例えばログ出力用のインスタンスをいちいちパラメータで全ての関数やクラスへ渡す必要が有ります。これは可読性的に許せないです。
haru666

2017/07/05 02:56

Loggerに対するサービスローケタパターンを悪とは言っておりません。 大体Configurationを横方向に展開する時、どこかでトップダウンな処理だけでは立ち行かなくなります。 しかしThreadLocalは明確に悪であると考えています。 ThreadLocalはグローバル変数の危惧された使い方の悪化バージョンです。 まあ、宗教戦争かもしれませんが。
Chironian

2017/07/05 03:23

例えば、スレッド毎に異なるログ・ファイルへ出力したい時、スレッド・ローカルを使うとプログラム構造がすっきりして好ましいと思います。 しかし、これ以上は質問の議題から離れすぎですのでこの辺で。 必要であれば「ThreadLocalは明確に悪であると考えるが何故にサポートしている言語が多いのか?」的な質問を立てられると良いかもしれません。
PorkCutlet

2017/07/05 05:57

ThreadLocalの生存期間はスレッドの生存期間と同じなのでは? グローバルの汚染はなにを指されています?
haru666

2017/07/05 06:22

スレッド毎に存在するグローバル変数のようなもの≒ThreadLocalという意味です。 ちょっと飛躍が過ぎましたね。 私は基本的にコルーチンで使えるような実装、つまりコンテキスト非依存なコードの集合の方が良いと思っています。 スレッドの管理者はスレッドローカルに触れていいでしょう。 コンテキストの管理者も実行コンテキストに触れていいでしょう。 しかし、サブルーチン内に隠れた先でそういったサービス全体に関わるようなコンテキストと触れあうというのは、相当作りこんで初めて許されるものだよなぁ、と思う次第です。
guest

0

性能の話に絞って、用途別にどのクラスを使うべきか、私の認識を整理するとこんな感じになります。

■10秒以上の長い処理
性能的にはどのクラスを使っても同じなので好きなのを使って良い。一応、この中では最もシンプルでオーバーヘッドが少ない Thread を使うのが最適。Task を使う場合は LongRunning オプションを付ければ Thread を使ったときと同じになる(ThreadPool を使わなくなる)ので好みで付ける。

■レイテンシ重視のタスク処理、非同期処理
Task 固有の機能(終了待機、例外処理)が必要なときは Task、そうでない場合は ThreadPool が最適。Task を使うときは必ず PreferFairness オプションを付ける。付けないと、高負荷時にワークスティーリングの影響でレイテンシが超不安定になる。例えば平均1msで終わるタスクで、時々1000msかかるタスクが出てくるとかも起こり得る。Graniさんの、これが原因で不安定だったのかも。

■スループット重視のタスク処理
一応 Task が最適。ワークスティーリングの効果で ThreadPool よりタスク管理のオーバーヘッドが少ない。ただ、経験上、ThreadPool との差はほとんど分からないレベル。ワークスティーリング機能の特徴でタスクの実行順がぐちゃぐちゃになるので、扱うデータの種類によっては、CPUキャッシュが効果的に働かず性能が出ない場合もある。その場合は PreferFairness オプションを付ける。PreferFairness オプションを付けると実質 ThreadPool と同じになるので、Task 固有の機能が不要なら ThreadPool を使った方が良い。

■GUIで5秒以上の長い処理を実行
単純な処理のときは BackgroundWorker が最適。複雑な処理のときは ThreadPool と Dispatcher を組み合わせて使うのが最適。BackgroundWorker の実行は ThreadPool で行われるので性能は ThreadPool と同じ。GUI以外での利用は想定していないと思われる。

■極限まで性能を出す必要のあるタスク処理
CPU論理スレッド分のスレッドを立てて、スレッド関係を固定し、NUMA構成とキャッシュを考慮し、自力でスケジューラーを書く。SQL Server がこの方式。Graniさんのもこの方式。この場合、制御方法に特徴があるから性能が出るのであって、Thread を使ったから性能が出ると言うわけではない。他のクラスを使っても同じ性能が出る。

■ThreadPool と Task の動作の違い
ThreadPool は単一のキューでタスクを管理するシンプルな方式。Task はデフォルトではワークスティーリングと言って単一のグローバルキューと複数のローカルスタック(ワーカースレッド毎にある)でタスクを管理する方式。キューよりスタックの方がオーバーヘッドが少なく、キャッシュが効きやすい。また、スタックがワーカースレッド毎に存在するため、スレッド間同期のオーバーヘッドが少なくて済む。頻繁に追加タスクが発生する場合やコア数が多いCPUを使っている場合は性能的に有利になる。
Task のワークスティーリングの説明
https://blogs.msdn.microsoft.com/jennifer/2009/06/26/work-stealing-in-net-4-0/
Local Queue と書いてあるが実際の動作はスタック。
Taskは終了待機(スレッド間同期)の機能がある分、オーバーヘッドが多い。ただ、ThreadPool を使っても結局自分でスレッド間同期のコードを書く必要があるので、全体としては変わらない。

■スループットとレイテンシ
スループットは単位時間にこなせるタスクの量(数)。レイテンシはタスクを依頼して結果が返ってくるまでの時間。ThreadPool がスループットとレイテンシのバランスが取れているのに対し、Task のデフォルト(ワークスティーリング有効)はスループット特化型でレイテンシは平均的に長く、不安定。

■サービスの実装
haru666さんも書かれていますが、一般的なサービス、特に不特定多数から同時にリクエストを受けるネットワークサービスを書く場合は、スタートアップコードで非同期処理を開始して、以降スレッドプールで処理するのが性能的には一番良い方法になります。この場合、メインスレッド的な固定スレッドは必要ありません。サービス提供先が限られた相手しかいないときは、メインスレッド的な固定スレッドを最初に起動して処理した方が実装が簡単で良いと思います。

■結論
性能的に見て、新しいから必ず Task が良いと言うわけではなく、用途に応じて使い分けをした方が良いです。特に Task のデフォルト動作、ワークスティーリングの動作には注意が必要です。私は Task はあまり使わず、ThreadPool で書くことが多いです。Task は機能的に細かい制御がやりづらいし、性能的にも不安定で扱いにくい感じがしますので。

投稿2017/07/11 15:13

編集2017/07/11 23:03
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

あまり詳しくない自分がレスするのも何ですが・・・

質問者さんの言われる Thread とは、「Threadはもう古い、時代はTaskや!」という言葉から想像して、Task とか async / await がなかった時代の Thread のこと、つまり以下の記事で言う Thread のことですよね。

.NETにおけるマルチスレッド・プログラミングの方法
http://www.atmarkit.co.jp/ait/articles/0504/20/news111.html

その記事に書いてありますが "サーバ型のプログラムのように、リクエストを並行して処理するようなプログラムの場合、スレッドの生成・破棄を大量に繰り返す必要が出てくる。スレッドの生成にはそれなりのリソースが消費されるため、単純にこれを繰り返していてはパフォーマンスが低下する" というデメリットがあるそうです。

上に紹介した記事に書いてありますが "この問題を解決する仕組みが「スレッドプール」である" ということだそうです。

そして、Task は以下の記事に書いてありますように ".NET Framework 4 では、スレッド プールをより使いやすくするために、Task(System.Threading.Tasks 名前空間)というクラスが導入されました" ということで、基本的には ThreadPool だそうです。

[雑記] スレッド プールとタスク
http://ufcpp.net/study/csharp/misc_task.html

ということで、Thread と Task を使うのは最初の記事のメリット / デメリットを天秤にかけて決める話ではないかと思います・・・が、MSDN Blog の記事(URL 下記)によると、Thread を使うのは、その記事を書いた Microsoft の開発者よりはるかにスマートに実装できるのでなければ "don't even think about it" だそうです。

Performing Asynchronous Work, or Tasks, in ASP.NET Applications
https://blogs.msdn.microsoft.com/tmarq/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications/

理由はその記事の FAQ の 4 番目に書いてありますが、以下に概略を書いておきます(誤訳はあるかも)。

(1) CLR ThreadPool を使用するのに比べて非常にコストが高い。

(2) 自分で作った Thread に I/O 要求が残ってないか終了前にチェックしなければならない。

(3) システムのパフォーマンスを保つには実行されている Thread の数が適切でなければならないが、自分で Thread を作るのであればパフォーマンスを保つのは自分の責任になる。

そう言われては、少なくとも自分的には Thread を使うという選択肢なないかなと思ってしまいます。

ご参考まで。

投稿2017/07/05 03:21

編集2017/07/05 03:23
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

PorkCutlet

2017/07/05 07:20

やりたいことは、本当にただ処理をするスレッドを作りたいだけでタスクのスケジューリングとかは不要ですし、例外のハンドリングも含め処理スレッド側で完結させるので、管理側がすることは開始要求・停止要求程度でいいのです。 (正体はWindowsサービスです。ただしサービス以外でも起動させたいので、管理側と処理スレッド側は最低限のインターフェースで繋がっていて、双方相手が何者かわからないまま動作することが望ましいのです。) プロセスを分けてしまえ!というのもありですが、それはそれでプロセス間通信を考えないといけなくなるので面倒なのです。 ゆえにその3つの問いの回答は・・・ (1)スレッドプールの方がコストが高いと思うけども。 (2)当然そのあたりも踏まえた完結した処理になっている。 (3)1個しかスレッド走らないしメインスレッドは待機状態、同じ処理をメインで行ってもパフォーマンスはほぼ同じ。 >そう言われては、少なくとも自分的には Thread を使うという選択肢なないかなと思ってしまいます。 そう言われてもThreadな気がするので、この質問なのです。
退会済みユーザー

退会済みユーザー

2017/07/05 07:48

質問者さんが、Thread と Task (ThreadPool) のメリット / デメリットを天秤にかけて Thread を使った方がベターと判断し、上に書いた (1) ~ (3) その他 Thread の使用に付随する問題は承知の上&アンダーコントロールということであれば、ご自分が決めた方向に進めば良いのでは? ここで議論する話ではないと思いますけど・・・
hsk

2017/12/26 03:42 編集

横から失礼します。SurferOnWwwさんに同感です。 質問主様の質問内容に、具体的に「Windowsサービスで、サーバー的処理を行うスレッドを立てたいのだが」と明示すべきでしたね。具体的な記述が少なかったために、課題が広くなってしまい宗教戦争っぽくなってしまいました。 漠然とした提題下でTaskを否定する回答が得られて、質問主様やこのQAをみた方から「Taskはあかん、Threadで書きなさい」とTaskを否定される(TaskをDisられる)のは嫌でございます。。TaskとThreadとBackgroundWorkerとで、選択を誤るとマシンがヒーヒー唸って動かなくなってしまうような重い処理をさせるコードを書くためで困っているのなら、サンプルコードや計測結果を提示して議論を投げかけてほしかったです。 このご質問、半年も前のものだったのですね...C#トピックのトップページ内に上がっていたのでホットな状態なのかと勘違いしてしまいました。
guest

0

既定では ThreadPool 相当ですが、TaskCreationOptions.LongRunning オプションもあります。
そのため、従来の ThreadPool と Thread を同じように簡単に使えるものとして整頓したものと考えて良いかと思います。
ぱっと見、LongRunning時はThreadを利用しているようですので、動作後の差はなさそうです。

BackgroundWorkerは… 動作的に怪しかったので使ってません。

投稿2017/07/05 03:35

編集2017/07/05 11:07
mituha

総合スコア385

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

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

0

最近でも、こういうthread事例もある。 リアルタイム通信におけるC# - async-awaitによるサーバーサイドゲームループ

Taskは小さい処理をたくさん使うのには向いているとはよくいう。

BackgroundWorkerは、お亡くなりになりました。UWPには、入っていない。

投稿2017/07/05 02:22

kiichi54321

総合スコア1984

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問