X

C#, C♯, C#相談室 Part95

■ このスレッドは過去ログ倉庫に格納されています
2017/10/17(火) 00:41:22.60ID:JxIRdCj70
■Visual Studio 2017 Community(無償の統合開発環境)等はこちら
http://www.visualstudio.com/downloads/

■コードを貼る場合はこちら
http://ideone.com/

■前スレ
C#, C♯, C#相談室 Part94
http://mevius.2ch.net/test/read.cgi/tech/1492843013/

■次スレは>>970が建てる事。
建てられない場合は他を指定する事。
VIPQ2_EXTDAT: checked:vvvvv:1000:512:----: EXT was configured
621デフォルトの名無しさん (ワッチョイ e12d-XiJJ)
垢版 |
2020/01/04(土) 01:17:00.82ID:ebUznjxj0
誤った指摘をしている人がいますが、>>610は、相当ミスらない限り並列処理かつ非同期処理です
並行処理である保証は全くありません
2020/01/04(土) 02:02:38.56ID:X7t3Qsuc0
並列は、CPU に使う用語

並行は、処理に使う用語
623デフォルトの名無しさん (ワッチョイ 426a-UAPS)
垢版 |
2020/01/04(土) 02:34:27.40ID:WRfbnwnP0
こんだけ暴れておいてこの結末w
2020/01/04(土) 02:47:20.03ID:oEJCGEWJ0
>>620,621
ファイルや通信のI/O処理中にCPUでは別の処理をするってのは
典型的な並行処理の例で一般的には並列処理とは呼ばないぞ

ファイルがパーティション分割されてて
100パーティション同時に書き込みを行うような処理なら並列処理

基礎的なことなのでもうちょい勉強してくれ
625デフォルトの名無しさん (ワッチョイ e12d-XiJJ)
垢版 |
2020/01/04(土) 03:01:30.66ID:ebUznjxj0
>>624
>>621は冗談で言ってるんだとは思いますし、何が一般的かは知りませんが、私はこの並行処理の記述に従って理解しています
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/
なお、私の知る限りでは他分野でも同じです
2020/01/04(土) 07:26:04.88ID:SQI5AQb9M
>>624
並行処理ってのは、単一の主体が短いタイムスパンで複数の処理を切り替えて処理することによって、まるで並列処理をしているように見せかける技術のことな
言うまでもないが、並列処理は複数の主体が、見せかけじゃなく同時に別の処理をしてる場合な

例えばこうだ
var t1 = CalcSomething();
var t2 = DownloadFile();
var t3 = ReadFile();

1つの物理装置が、少しCPU処理→少しファイル処理→少しネットワーク処理、と繰り返して3つの処理を同時に処理してるように見せてるなら並行処理だ

でも実際には、別々の物理装置によって計算、ネットワークアクセス、ファイルアクセスを同時に処理するので、これは並行処理ではなく並列処理だ

基本的なことなので、勉強してくれまじで
2020/01/04(土) 07:33:09.39ID:wUfYsbyMd
C#で並列処理を勉強しようとしたら大抵初めに出てくるParallel.Forすら知らないんでしょ
だから英単語出してきてまでそれは平行だ!とか指摘しちゃう
英単語わかってるなら並列だってわかるはずのにw

もう以前からびっくりするくらい知識が浅い
2020/01/04(土) 07:49:31.73ID:wUfYsbyMd
あとマルチproccessとマルチthreadも同じやね
using System.Threadingも書いたことなんだろう

C#に無知でこれらを知らないは別に良いけど一般的なソフトウェア開発で並列処理なんて書かないとかいう指摘も的外れ
C#に関することに無知なのは触ってなけりゃ普通のことだろうけど今や当たり前に行われる並列処理をスパコンのものでお前らにはわからんだろうな、とか言っちゃうのは技術者としてどうかと思う
2020/01/04(土) 08:29:25.67ID:zoxkJgWd0
プログラム内の厳密な並列ってなくね?
おそらく無理じゃね
同じメモリ空間をCPUが同時にアクセスできないよね?
paralle.forとか俺はこんないい加減な前準備でできると思ってないけどね
どういう仕組みか知らんけどw
多分なんちゃってだろ
やった感じ直列で処理したほうが早い感じになってうんこだったよ
ちなみにフルHDの画像処理を上から三等分にしてparalle.forでやってみたがクソ遅い上に並列にやってない気がしたけど
みんなはこんなもん使えてるの?

ところでスレッドってスレッドスイッチするし積まれたタスクを順番に処理してるだけだよな?
その切替タイミングはプログラム内のsleepやDoEventsだよね?
2020/01/04(土) 08:50:02.37ID:oslWCP6e0
変なの増えた
2020/01/04(土) 09:09:30.45ID:H9Ya7buR0
>>629
> その切替タイミングはプログラム内のsleepやDoEventsだよね?
いつの時代の老害だよ…
2020/01/04(土) 09:10:51.45ID:SF9EFyjm0
>>629
パイプラインとかキャッシュとかレジスタとかマルチスレッドとか、CPUの技術を少しは勉強したほうがいい
2020/01/04(土) 09:16:33.71ID:zoxkJgWd0
>>631
え?じゃあどこ?
2020/01/04(土) 09:23:34.37ID:zoxkJgWd0
>>632
それを実際に言語の機能に適用してるかどうかは別だよね?

なんか超遅かったよ
もし並列に動いてるなら画像処理は単純に三分の一で終わったはずだよね?
ところがむしろ3倍以上かかってるんだな
なんか前準備に色々条件があるのか?
こんなもん役に立たないのか?
該当する処理が本当に適用できるのかはチェックが必要だと思うな
2020/01/04(土) 09:34:32.95ID:ljwPgx+b0
スレッド切り替えと言うが、今日日マルチコアだぞ。
Parallel.Forも一つだけど、PLINQなんかも実は色々効いてくる。
まあ、Taskは便利よ。
スレッドプールを有効利用するのは手でやると事故るので、Taskに任せるほうがよかろう。
その上でUIスレッドに返したければUIスレッドに返すコード書けば良いだけなんだし。
逆に言うと、UIスレッドからTaskをawaitしたときに元のスレッドに戻って来てる事自体が例外的な処理に近い。
2020/01/04(土) 09:44:36.22ID:wUfYsbyMd
parallelにしてもちゃんと理解してないと遅くなることだってありうるよ
並列化できない処理をparallelしたって切り替え処理とかが無駄に働いて逆に遅くなることもある

コードでも上げてみりゃどこが間違ってるか指摘できる人もいるんじゃない?
2020/01/04(土) 09:49:49.34ID:zoxkJgWd0
>>636
コードを見ないとわからない?
IDEが教えてくれる?
なんにせよ使えないよそんなの
2020/01/04(土) 09:54:48.34ID:zoxkJgWd0
>>635
それ並列でやった処理結果まとめられないじゃん
やりにくいし

結局処理単位は自分でブツ切りにしないと途中経過出力できないし
実質この手の機能ってc++の頃から別に便利でもなんでもないゴミクズ機能で停滞してるよね?
2020/01/04(土) 09:57:09.90ID:H9Ya7buR0
>>633
プリエンプティブ でググってこい
2020/01/04(土) 09:59:40.19ID:wUfYsbyMd
>>637
いや、あんたが何かを勘違いしてるかもしれないことをコードレビューしてあげようかって言ってあげてんのw
詳細な実装は開示しないけど俺が試したら遅くなった!parallelなんかまともに使えない!って主張なの?
世界中のプログラマが有益に利用してるんだから間違って利用しちゃってるなら正せばいいだけじゃん
ググりゃ腐るほど日本語でも記事はヒットするんだし
2020/01/04(土) 10:01:55.73ID:wUfYsbyMd
3分割したら3倍異常遅くなるって例えば各スレッドでファイルを読み込んでるだけじゃねーの?
そんなやり方したらそりゃ遅くなるよね
2020/01/04(土) 10:02:04.61ID:zoxkJgWd0
>>640
フルHD画像処理を上から三等分でparalle.forって言ってんだからやって動くサンプル出してこいよ
おそらくdobon辺りに貼るだけでparalle.forかけて画像処理ループさせるだけだ
10分だぞ
やりたきゃ頑張れ
2020/01/04(土) 10:14:00.73ID:WRfbnwnP0
GAIJI vs GAIJI
2020/01/04(土) 10:18:25.47ID:dtJSIh3jp
ヤベエ逸材多過ぎだろこのスレw
今までどこに潜んでたんだコイツら
2020/01/04(土) 10:31:54.67ID:ljwPgx+b0
>>638
纏められるよ。
PLINQ使ってみ。
途中経過が必要ってこと自体、多分並列化出来てないから考え方がおかしいよ。
並列にやってるんだから途中経過なんて足し込まないと出せない事はやるべきじゃないでしょ。
足しこみは並列にできないんだから、そこで足並み揃えちゃったらそりゃ並列に動かんよ。
2020/01/04(土) 10:57:29.93ID:kFIotbKU0
まあとりあえず、「並列」「並行」については最近は混同されてるし、実際混同しても問題ない領域が多いし、
文系馬鹿C#erが主流なこのスレでその厳密性を求める意味はない。
ただまあ、ファイルとCPUでは速度差がありすぎるから、
まともなスケジューラーなら並列に書いてても並行になってしまうとも思うが。
しかしMSはそこも含めて隠蔽しようって事なんだろ。これ自体はいい。

> Parallel.For
これはちょっと筋が悪い。現在の主流はMap/Reduceなんだから、そっちに合わせた方がよかった。
お前らが速くなるならないでグダグダ言っているのも、結局はこれで、Map/Reduceが効く場合は速くなり、
そうでない場合は速くならず、場合によっては遅くなる、というだけ。別に不思議なことではない。

ただまあ、君らも分かっているとおり、レンダリングの場合は分割は効果があるから、
・書き方が悪い
・今はそこまでParallel.Forの出来がよくない
のどちらかで、まあそれを揉めているわけだが、今の状況はさておき、
最終的にはこのコードで簡単楽チンに数倍速を得よう、ってのは間違ってはいない。

問題はやはりMap/Reduceでないことで、結局、「関数」で処理を抽象化出来ているから
関数を直接扱う「関数型」の方がI/Fは綺麗に並んでしまう。
そこをForにこだわったのは間違いだと思うよ。
2020/01/04(土) 11:03:02.06ID:DH3JGq6p0
とりまコード見ないとなんとも
なんかで排他制御でも効いてるんだろうけど
2020/01/04(土) 11:03:38.49ID:oEJCGEWJ0
>>625
そのリンク先に並行処理についての記述は一切無いぞ

>>626
並行処理をせまく理解しすぎ
並行処理と並列処理は観点の違う概念であって相互排他的なわけではない

並行処理はある瞬間を切り取ると”必ずしも”同時に複数の処理が実行されているわけではないだけで同時に実行されてる場合もある

君の例は1つの物理装置で処理されてようが別々の物理装置によって同時に処理されてようが関係なく並行処理(Concurrent Processing)の例
それを並列処理とは呼ばない
2020/01/04(土) 11:11:54.60ID:8gIJKMuI0
そもそもawait/asyncは、非同期処理を同期処理のようにかける仕組みであって
マルチタスクそのものじゃなくて周辺技術だよな
2020/01/04(土) 11:53:37.81ID:SQI5AQb9M
>>648
いや、そっちが理解間違ってるよ

並列処理は複数の装置で複数の処理を同時に実行すること

並行処理は単一の装置に複数の処理をスケジューリングして、順番に実行することによって巨視的に並列処理のように見せかけること

複数の装置にスケジューリングすることを並行処理と呼んでる場合もあるが、それは正確には並列処理と並列処理のハイブリッドだな
君が言ってる同時に処理される場合もある、というのはこのことだろうな
2020/01/04(土) 12:07:21.44ID:hpecUN4N0
>>650
どっちが正しいと断言するつもりはないけど、この並列処理と並行処理の定義はどこから持ってきたものなの?
2020/01/04(土) 12:08:56.85ID:ljwPgx+b0
>>646
自動的に適切な単位に分割されたMapとReduceがPLINQで実現できると思うんだが。
2020/01/04(土) 12:27:07.45ID:LH34clIMM
>>651
放置しときなよ
用語知ってる俺スゲー君同士の戦いなんてどうでもいいし
2020/01/04(土) 13:10:03.26ID:9r4/dVyW0
この年末からのつまんねえ言葉遊びの流れほんとクソ
2020/01/04(土) 15:56:23.34ID:zGBEMeLs0
装置どうこうで並列や並行いってるやつらは
まずマルチコアなCPUを装置としてどう見てるのか書け
話はそれからだ
2020/01/04(土) 19:35:04.89ID:kFIotbKU0
>>652
実際効果が出ているのならそれでいいと思うよ。
MapかForについては、どっちから攻めるかの違いだけではあるから。

ただ、分割をC#側が担うのは明らかに間違ってるでしょ。
DBならSQL投げてその先はDB側で動的に何とかしろ、が正しく、
当たり前だがDBの構成なんてC#コーディング時に関知しようもないし。

といってもMSがこの辺を知らなかったはずもない。
何か作戦があるんだとは思うよ。

PLINQについては確かに「並列」だが、なかなかな事を書いている。
> 既定では、PLINQ はホスト コンピューター上のすべてのプロセッサを使用します。
> https://docs.microsoft.com/ja-jp/dotnet/standard/parallel-programming/introduction-to-plinq
> 結果の順序は毎回異なることがあります。
> この動作は、オペレーティング システムによるスレッドのスケジュール方法に依存するため、アプリケーションでは制御できません。
> https://docs.microsoft.com/ja-jp/dotnet/standard/parallel-programming/order-preservation-in-plinq
これはMSが悪いわけではなくて、当然そうにしかならないのだけど、
当たり前だがPLINQに丸投げすれば全てよし、みたいなものではない。(ただ、そこを目指してはいるのは正しい)
まずは書けないと話にならないので、MSとしてはプログラミングモデルを提供してきた、というところか。
2020/01/04(土) 19:37:21.95ID:kFIotbKU0
asyncも、ググれば分かると思うが、実はasync/awaitの片方はキーワードとしては要らない。
その場合には実行/フェンスについて、実行は今まで通り記述した時点で開始、
フェンスは結果を使うところで暗黙的に、ということになる。(つまり今ならawaitが要らない)
これはこの界隈ではすごく一般的な考え方で、
例えばアセンブラでDIVやSQRT命令みたいにレイテンシが長い命令を配置したとき、
結果レジスタを使わない場合はどんどん流し、結果レジスタを使う場合だけそこで一旦停止して結果待ち、という事を30年前からやっている。
だから「非同期」というよりは「並列化+パイプライン(可変長レイテンシ)」として考える方がいいのかもしれないけど、
いずれにしても今は「明示的にawaitを書く」というある意味MSらしくない、
どちらかというとWeb系的ドベタ仕様で、だからこそ君らもTaskマンセーな訳だが、
こう説明されれば「あ、確かにawaitいらねえな」とはすぐに分かるだろ。
多分君らが非同期にだいぶ慣れた頃にawaitは廃止されると思うよ。
そして「非同期」と「同期」は一文字も変わらない同じ関数で実行可能となり、完全な抽象化が実現出来ることになる。

ただし、今の仕様が悪いか、と言われれば、必ずしもそうでもない。
俺がさんざん言っているとおり、MSは若干エレガントなところを狙いすぎていて、
ライト層がちょっと置いてきぼりになってる感がある。(Web系に比べて)
そしてさんざん君らがTaskマンセーしているとおり、ベタな仕様には分かりやすいという大きな利点がある。

ただそれにしても、繰り返すが、CPUのパイプライン構造を知っていれば、あ、確かに間抜けな仕様だな、とはすぐに分かるだろ。
俺が信者だと揶揄しているのはそこら辺であってさ。
2020/01/04(土) 19:51:30.64ID:dJY1KQxf0
別スレ立てたら?
2020/01/04(土) 19:54:05.88ID:kFIotbKU0
もしかしたら伝わらないか?とも思うので一応。
俺はawaitを廃止して、以下の
> 次に、ベーコンと卵の await ステートメントを、メソッドの最後の朝食提供前に移動します。
> https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/concepts/async/index
の下のコードを以下に出来る、といっている。

Coffee cup = PourCoffee();
Console.WriteLine("coffee is ready");
Egg eggs = FryEggs(2);
Bacon bacon = FryBacon(3);
Toast toast = ToastBread(2);
ApplyButter(toast); // ここでtoastが完了してないときだけは結果待ちで止まる
ApplyJam(toast);
Console.WriteLine("toast is ready");
Juice oj = PourOJ();
Console.WriteLine("oj is ready");

Console.WriteLine("eggs are ready");
Console.WriteLine("bacon is ready");
Console.WriteLine("Breakfast is ready!");

まあみりゃ分かるとおり、await文部分を前に持っていっただけではあるが。
今の仕様だと、この書き方では肝心の非同期部分が1つずつステップ実行されてしまう、という事になっている。
2020/01/04(土) 20:06:59.76ID:tMXF89W90
>>659
そのコードじゃ非同期処理が完了してなくても"〜 are ready"って表示されるだろ。
2020/01/04(土) 20:09:00.48ID:DH3JGq6p0
c++スレにいた長文マンかなこいつ
2020/01/04(土) 20:44:38.22ID:kFIotbKU0
>>660
まあそこはツッコミ来るかとは思っていたが…。

ぶっちゃけ、その通りだ。そしてそれで問題ないんだよ。
結果を確認しに行けば確かに出来ている(ようにしか見えない)からね。
時間軸上で遅延が発生するだけで、論理的な動作としては全く問題ない。

これは例えばJavaScriptでは大昔から実装済みで、getElementsByClassNameがそうなってる。
https://developer.mozilla.org/ja/docs/Web/API/Document/getElementsByClassName
これで問題が発生しているケースなんてない。
馬鹿が「getElementsByClassNameは圧倒的に速い」みたいなブログを書いている、というのは結構あったが。

ただ、まあ、何らかのフェンス構文自体が必要なのは認める。
しかし、当然だがフェンス自体は不要なら書かないものだし、
普通に「返り値を使う」いわゆるお行儀のいいプログラミングをしている限り、実際に不要だ。
だからじきに、みんなが「await って実は要らなくね?毎回お約束的に書かされるだけだろ。」
と思いだした頃に、廃止されるんじゃないかな。
そしたらその階層を取り扱う必要もなくなり、Taskも廃止できる。
663デフォルトの名無しさん (ワッチョイ 7197-IH4P)
垢版 |
2020/01/04(土) 20:59:50.92ID:W0mLC2oD0
>>657 >>662
awaitの結果を必ずしも使うとは限らないのに、本気で言ってるの?
async Task<void>のメソッドなんていくらでも作ることあるだろ。
そりゃ、async Task<bool>にでもしてtrueでも返すようにして、if文で判定するとかはできるけど、そんなの正直言ってasync/awaitからの退化だよ。
C#では非同期実行の方が基本的にはあえてさせることなんだから、awaitなくしたとして
コードを読んでてもわからないところが非同期になっていたら結構困ると思うけどなぁ。
なんでもかんでもどうやらある程度経験が豊富そうなJSを基準に考えちゃうみたいだけど、非同期が当たり前のJSとはとりまく環境が違うと思うよ。
2020/01/04(土) 21:49:39.49ID:kexvLmFr0
await不要って園児並みに相当バカ
無くなったら何が困るかの簡単なことに気づかないとか、普通の人でもわかることだよw
2020/01/04(土) 21:59:07.73ID:xLbjEwkrM
そろそろ冬休み終わるから謎の長文更新も途切れるかね?
2020/01/04(土) 22:10:43.14ID:hpecUN4N0
冬休み関係ない人かもしれない
2020/01/04(土) 22:16:18.30ID:SQI5AQb9M
前にも言ったがそんなに素晴らしいものなら、C#の言語チームに提案してこい
誰にも相手にされんだろうが、ここでグダグダと怪文書を書き込み続けるよりは生産的だろ
2020/01/04(土) 23:11:07.21ID:kFIotbKU0
>>663
> コードを読んでてもわからないところが非同期になっていたら結構困ると思うけどなぁ。
これはその通り。だから俺の理想は以下のコードになるけど、
これはおそらくプログラミング理論的には>>659より汚いコードだとされる。(抽象度が落ちてる)

Coffee cup = PourCoffee();
Console.WriteLine("coffee is ready");
Egg eggs = async FryEggs(2);
Bacon bacon = async FryBacon(3);
Toast toast = async ToastBread(2);
ApplyButter(toast); // ここでtoastが完了してないときだけは結果待ちで止まる
ApplyJam(toast);
Console.WriteLine("toast is ready");
Juice oj = PourOJ();
Console.WriteLine("oj is ready");

async_fence(); // これ以前のasync関数はこれ以降は完了していることが保証される
Console.WriteLine("eggs are ready");
Console.WriteLine("bacon is ready");
Console.WriteLine("Breakfast is ready!");

現行からの変更点としては、
・キーワードawaitをasyncに変更、書く場所は同じ、ただしwaitせず実行して貫通
・キーワードasyncは呼び出し側に明示的に付け、定義側には要らない
・必要ならasync_fence()でフェンス、無ければ実行結果が使われるときに自動的にフェンスされる
・Egg/Bacon/ToastはTaskではなく値、よってキャンセル等は面倒だがどうせしないからよし
ただこれだと async を async()として関数化してリッパーにすれば現行のC++等で実装出来そうな気がしてきた。
これは勝手にやってみるかも。

> 非同期が当たり前のJSとはとりまく環境が違うと思うよ。
コミュニティとしては君らの方が慣れてないだけで、プログラミングとしては大して変わらんよ。
JSもI/O以外は全部同期だし、非同期部分は限定されてる。(なおgetElementsByClassNameは非同期ではなく遅延評価)
2020/01/04(土) 23:27:22.94ID:Zo3qJxMY0
仕様を劣化させてるだけじゃん…
2020/01/04(土) 23:40:07.01ID:y+CTQpVr0
>>668
暇だからリファクタリングしてあげた

var cup = PourCoffee();
Console.WriteLine("coffee is ready");
var eggs = FryEggsAsync(2);
var bacon = FryBaconAsync(3);
var toast = await ToastBreadAsync(2);
ApplyButter(toast);
ApplyJam(toast);
Console.WriteLine("toast is ready");
Juice oj = PourOJ();
Console.WriteLine("oj is ready");
await eggs;
await bacon;
Console.WriteLine("eggs are ready");
Console.WriteLine("bacon is ready");
Console.WriteLine("Breakfast is ready!");

コイツの管理者はコードレビュー大変そう
2020/01/04(土) 23:47:15.01ID:+Qzz4bCZ0
毎日毎日赤っ恥書きながらも上から目線を崩さない姿勢はだんだん可愛く見えてきたなw
2020/01/04(土) 23:59:24.33ID:kFIotbKU0
>>670
それはawaitで書けばほぼ現行通りだろ、というわけか。
まあその通りだが、呼び出し側に async が付いているのがミソなんだよ。
今はそれが Task<TResult> だから明示的だが、var になると明示的でなくなる。これがよくない。

また現行の await は事実上フェンスとして使われているから、
君が書き直したその通りなのだけど、俺は既に言ったが、
「フェンスは出来るだけ使わない」(というよりこれは常識とされる)ので、ここが気に入らない。
書かずに済むのだから書かすなよ、だ。

そして現行の関数宣言部、 async を付けるわけだが、これは意味的に要らん。
(現行の仕様でも特に要らないはず)
ジョブの最上位関数はマルチスレッド/シングルスレッド./同期/非同期関係なく同一に書ける。
それをどう呼び出すかで同期/非同期等切り分けるべきであり、
定義側にわざわざ async と非同期専用みたいに書くのが気に入らない。
同期で呼び出したら同期で動作するだけの関数なのに、だ。
2020/01/05(日) 00:05:02.27ID:UANz5iul0
>>670
ああ、だから俺は、違いは

同期:
var eggs = FryEggsAsync(2);

非同期:
var eggs = async FryEggsAsync(2);

だけにして欲しいな、ということ。
現行のコードに async を挿入するだけでコアが余っていれば非同期でその関数が実行され、高速化する、ということ。
2020/01/05(日) 00:17:31.34ID:3JPcR/pBM
言語の感想文はブログで書け
薄っぺらい知識なのを宣伝してるだけだぞw
675デフォルトの名無しさん (ワッチョイ be02-AVGY)
垢版 |
2020/01/05(日) 00:37:05.87ID:T90rRrA70
>>672
あなたの考える仕様はvarの比ではなく、暗黙的でわかりにくい
普通に変数にアクセスしているだけなのに、非同期処理と待ちが入るなんてはっきり言って迷惑

それと呼び出し先を非同期/同期の両方に対応させる設計は良い習慣ではない
・CPUバウンドなら同期的
・IOバウンドなら非同期的
大まかにこの基準で切り分けて、それをシグネチャで明示したほうがいい
2020/01/05(日) 02:47:09.06ID:hKu0nmGg0
C#の仕様策定プロセスはオープンなんだからこんなところでウダウダ言ってないでgithubで提案してみれば?
ツッコミ入って「C#コミュニティはクソ!」って言い出す未来しか見えないけどさ
2020/01/05(日) 04:32:02.28ID:Bbmuqtw40
まさかと思うけど、asyncなメソッドはawaitしないと呼び出せないとか思ってるんじゃないか
2020/01/05(日) 09:05:43.12ID:UANz5iul0
>>675
varがわかりにくいというのはお前の慣れの問題。

> 待ちが入る
待っているのは同期設計だ。
毎行で「前行の終了を待つ」からブロッキングと呼ばれる。

> それと呼び出し先を非同期/同期の両方に対応させる設計は良い習慣ではない
そんなわけあるか。もう一度言うが、非同期ってのは呼び出し方法であって、ジョブそのもの(関数)の性質ではない。
例えば、MatrixMulという重たい計算があったとする。
すると、日常的にC#で並列をこなすお前らは、これを高速化する為に、Task<TResult>に分割するわけだろ。
その場合、MatrixMulは「同期関数」だが「非同期」で実行される。
「非同期」ってのは関数の性質ではなく、呼び出し方であって、逆に、「非同期関数」を「同期」で呼び出すことも当然出来る。
だから被呼び出し関数に async を付けること自体がナンセンスなんだよ。
付けるとしたら、呼び出し部分か型で、
var eggs = async FryEggs(2);
AsyncTask<Egg> = FryEggs(2);
であって、お前の流儀は
Task<Egg> = FryEggsAsync(2);
なんだろうけど、これはナンセンスなんだよ。ハンガリアンならぬ、アシンカリアンでしかない。

だから、今の仕様は
A. 非同期に慣れてないC#erへの補助輪
B. ヘルスバーグが中二病全開
C. 実はコンパイラの都合で、async付けてくれればパッチ当てがメチャ楽だったから適当こいて付けさせた
のどれかで、俺はBだと思うけど。

なお気持ち悪さではSQLをべた書きするLinqの方が上だと思う。
でも linq を使った関数に一々 linq を付けることもないし、
同様に parallel を使ったら parallel を付けて回る、ということもないんだろ。
await 使ったら async 付ける、ってのは全くナンセンスだよ。
非同期は、今後は、今のお前らが思っているほどは特別なものではなくなるんだよ。これはもう確定してるだろ。
2020/01/05(日) 09:35:53.95ID:kO8WyPRk0
>>678
async/await考えた人が元々asyncは必ずしも必要ないと言ってるのに、何をさも自分が考えたように言ってるんだ?

awaitいらねーとか真正アスペかよ
2020/01/05(日) 10:52:51.13ID:T90rRrA70
>>678
自分はvarがわかりにくいとは思ってない
>var になると明示的でなくなる。これがよくない。
あなたがvarをよく思ってなさそうなので、あなたの考えた謎仕様のほうがそれより遥かにわかりにくいですよ、と言っただけ

>そんなわけあるか。もう一度言うが、非同期ってのは呼び出し方法であって、ジョブそのもの(関数)の性質ではない。
これも間違い
例えば、ネットワークやファイルなどIOバウンドな処理は、CPUとは異なるデバイスで処理されるので、原理的に非同期にするしかない
呼び出し先の性質によって非同期が確定する典型例

CPUバウンドの場合、呼び出し先で非同期をサポートすることも可能だが、基本的にそうする必要は無い
スレッディングのコストは無料じゃないのだから、呼び出し先はすべて同期的に実装して切り替えオーバーヘッドを減らしたほうが、全体的なパフォーマンスが向上する
UIと止めずに応答性を高めたいだとか、非同期にする明確な理由が出来たらそこで初めてTask.Runすればいい

上で基本的にと書いたのは、CPUを食い尽くしてでもいいから時間的に早く処理を終わらせたい、という理由で並列化する場合があるからだ
この場合は、プログラムを並列処理用に最適化して設計するのが定石だ
なので、この場合に関しては逆に非効率的な同期版をサポートする理由がなくなる

asyncが構文として不要なのはわかってるが、そんなつまらない話はあなた以外はだれもしてない
2020/01/05(日) 11:21:56.38ID:dqyEtfEv0
なんで比較にLINQが出てくるのかめちゃくちゃ謎
SQLっぽい書き方のLINQしか知らないのかな?
メソッド拡張の方のLINQはmap/filter/reduceと書き方がちょっと違うだけの単なるメソッドを呼び出し
してるだけなんだけど。
2020/01/05(日) 11:33:14.86ID:kO8WyPRk0
>>680
657 デフォルトの名無しさん (ワッチョイ 797b-s4wZ) sage 2020/01/04(土) 19:37:21.95 ID:kFIotbKU0
こう説明されれば「あ、確かにawaitいらねえな」とはすぐに分かるだろ。
多分君らが非同期にだいぶ慣れた頃にawaitは廃止されると思うよ。

>>680
asyncが構文として不要なのはわかってるが、…

asyncもawaitも不要なんですね、真正アスペ君w
たったこれだけのシンプルな間違いさえわからない、自分で理解できてない
これが真正アスペでないと誰が言えようかw
2020/01/05(日) 12:17:09.89ID:As/vHaVrM
awaitは必要だぞ
2020/01/05(日) 14:01:08.94ID:UANz5iul0
>>680
なるほどお前が全然分かって無いというのは分かった。


根本的に勘違いしていると思うのだけど、ジョブの中身を同期専用/非同期専用で設計することはない。(というか、できない?)
既に言ったが、MatrixMul、要は行列の掛け算が100ジョブあったら、4CPUならそれを4個ずつ積むだけだ。
このとき吐けた順にガンガン積んで処理していきたいなら、
「非同期」にして最初から全部キューイングしてディスパッチャに任せるだけ。
ジョブ自体が「非同期」ではなく、ジョブの処理の仕方が「非同期」なんだよ。
MatrixMulを非同期専用に書き換える、なんて事はない。というか、出来ない。


> 例えば、ネットワークやファイルなどIOバウンドな処理は、CPUとは異なるデバイスで処理されるので、原理的に非同期にするしかない
これもない。というか、C#にしても、他の言語にしても、ファイルオープンは通常は同期だ。
ここはJavaScriptのスレではないのだが、それを間違えたか?

これについては「JavaScript 10k (またはc10k)」でググってくれた方がいいと思う。
Sleepがない方がパフォーマンスが出る!というのがJavaScriptの宗教だから、蕩々と説明してあるはず。
ただしJavaScriptもメジャーになってしまったし、おそらく以前ほど叩かれなくもなっているので、最近はこの話題も聞かないが。

I/Oを非同期として分離する必要があるのは、JavaScriptがSleep無しのシングルスレッドアーキテクチャだからであって、
Sleepありのマルチスレッドアーキテクチャならその必要はないし、C#含めて通常の言語は全部これだよ。
685デフォルトの名無しさん (アウアウウー Saa5-CnQr)
垢版 |
2020/01/05(日) 14:56:44.29ID:MI3jwdk/a
なんか言い争ってる両者ともそもそも同期非同期の意味が分かってない予感w
2020/01/05(日) 14:57:08.99ID:T90rRrA70
>>684
>要は行列の掛け算が100ジョブあったら〜
これは呼び出し先を同期的に実装して、呼び出し元で非同期実行してるパターン
>>680で言うと
>CPUバウンドの場合〜
の段落のこと
このパターンでは呼び出し先は同期版だけサポートすればよく、非同期版までサポートする必要はない
無意味に同期/非同期の両方をサポートしなくていい

>C#にしても、他の言語にしても、ファイルオープンは通常は同期だ。
違う
ファイルIOは背後で非同期的に処理されているが、APIの中でブロックしているから同期的に見えているだけ
昔は言語側の非同期サポートが洗練されていなかったため、妥協してこういう書き方に落ち着いた
C#ではTaskとawaitが導入されて、非同期処理の記述が大きく改善されたため、
原理的に非同期なものは余計なことをしないで、非同期なものとして作れば良い、ということになった
このパターンでは呼び出し先は非同期版だけサポートすればよく、同期版までサポートする必要はない

処理の性質によって同期版か非同期版のどちらかだけを作ればよろしい
2020/01/05(日) 15:01:43.69ID:jkDw/EWEM
こんなくだらん喧嘩の起きる余地がないGoが流行るのも納得
2020/01/05(日) 15:26:07.93ID:UANz5iul0
>>686
> 無意味に同期/非同期の両方をサポートしなくていい
無意味も何も、普通に作ったら両対応にしかならないと思うぞ。
逆に、そうならないのなら、コーディングを見直した方がいい。

後半については、多分お前の「非同期」は一般の意味とは違うと思うが、
同期APIと非同期APIの両方が用意されている場合、今後は非同期APIだけ使え、というのはお前の自由だ.。
ただ現実として世の大勢は同期APIで、そしてこれで全く問題ない場合が多く、そうはならないと思うけど。
(例えばファイルなら中身がないと次の処理が出来ず、話を進めようがない事が多い)
なお非同期縛りが心地よいのならJavaScriptを勧める。あれは宗教的にそうなってる。

今はAPIの中身についての話なんてしてない。それがお前流の逃げならそれでもいいが、
ここは「C#でどう書くか」の階層の話をするところであって、APIの中身ガーとか言うのなら最低限先にそう言っておくべきだろ。
ただ俺はそれについてつき合う気はないが。(他の人が食いつくのは自由)
2020/01/05(日) 15:40:34.39ID:eKdfVC3B0
そもC#はSTAとMTAの両方、なんなら混在する環境に対応しなければならないので
どっちかで綺麗に書けるかけるからこうすべきだってお花畑はなかなか通用しないのよね
結局C#においてはasync/awaitもTaskの中で頻発する特定のパターンを楽にしてくれるだけ

>今後は非同期APIだけ使え
新規のAPIではMSはそういう方針だねえ(winrt)
2020/01/05(日) 18:06:33.11ID:VTWLVkpA0
WPFではファイル操作関数を同期的に呼び出せたが、UWPだと許されない。
ちっちゃいファイルの読込みでGUIの遅延も体感できないぐらいだけどダメなんだ。
ちょっとしたプログラム書く時に面倒だね。
2020/01/05(日) 18:11:57.59ID:qdBxOc2v0
>>690
async/awaitあるから普通は問題無くかけるけど、コンストラクターでファイル弄るときは面倒なんだよな
2020/01/05(日) 18:23:07.47ID:VTWLVkpA0
>>690だけど、ちょっと間違った。
同期的には書けるけど、プライマリスレッド(GUI)からだとダメなんだ。
2020/01/05(日) 19:12:31.63ID:jkDw/EWEM
GUIアプリならネイティブスレッドのコストは問題にならないから、
GUIをフリーズさせたくないならイベントハンドラでスレッド起こしてあとは全部同期で書くのが一番シンプルで分かりやすい
最近のC#のasync信仰はWebで膨大なリクエストを捌くときの話で、WinのGUIアプリには全くと言い切っていいほど関係ないよ
2020/01/05(日) 19:23:11.93ID:kO8WyPRk0
>>693
guiのイベントでawaitじゃあかんの?
2020/01/05(日) 19:34:01.01ID:jkDw/EWEM
>>694
もちろんawaitはするよ。
await Task.Run(() => {
//あとは全部同期処理
})
イベントハンドラでこう書くだけ。
コントロールを触るときにInvokeが必要なことさえ忘れなければこれでいい。
ちなみにGoはこの考え方を更に突き詰めて、スレッドを独自の軽量な仕組みに置き換えることでWebも全部同期で書けるようにしてるね。
2020/01/05(日) 19:38:18.63ID:AZQzKocv0
invokeしても死ぬときあんじゃん?

→運が悪かったと諦める
→解決するまでひたすら回避策を突っ込んでいく
→マイクロソフトに電話かける
→上記を制限時間いっぱいまで全部やってみる
2020/01/05(日) 20:03:16.92ID:qqN6BGPlM
ファイルオープンは同期的とかいう謎の断定の声もあるけど、
UWPだとオープンも非同期なんだね。

https://docs.microsoft.com/ja-jp/windows/uwp/files/quickstart-reading-and-writing-files

アクセスするストレージへがローカルストレージだけじゃなくてクラウドストレージなのも一般的になってきたから、
ファイルを開くために必要な一連の操作もタイムアウトして失敗する可能性を考えなくちゃならなくなったということなのかな。
2020/01/05(日) 20:08:14.69ID:kO8WyPRk0
>>695
なんだ… それなら

〉最近のC#のasync信仰はWebで膨大なリクエストを捌くときの話で、WinのGUIアプリには全くと言い切っていいほど関係ないよ

とちゃうやん
頭ではわかっているのに言い方が間違ってる(言い方が悪い)人時々いるよな
2020/01/05(日) 20:47:26.26ID:VTWLVkpA0
>>695
GUIスレッドでawaitしたらブロッキングしてダメじゃん。
結局、同期呼び出しとおんなじになるよ。
700デフォルトの名無しさん (ワッチョイ 7197-IH4P)
垢版 |
2020/01/05(日) 20:59:12.88ID:dqyEtfEv0
>>699
UIスレッドでawaitしてもブロッキングにはならないと思うけど。
await以降のコードがawaitしている処理が終わったら実行されるだけで、
処理中は一旦asyncのメソッドを抜けてイベントループに戻るよ
2020/01/05(日) 21:07:50.78ID:3XFOch5ma
>>698
695の場合、どうせ後続に何も書かないんだからawaitはあってもなくても一緒じゃね
警告を抑制する以上の意味はないだろう
2020/01/05(日) 21:15:43.37ID:GaCs2bDS0
>>699
awaitを誤解してる
Task.Wait()みたいにブロッキングはしない
awaitより後ろの処理が自動的に継続タスクになるから同期処理っぽく見えるだけ
2020/01/05(日) 22:16:53.04ID:kO8WyPRk0
>>701
実行ボタンの場合、何も書かないほうが稀だと思うけど
2020/01/05(日) 22:31:27.48ID:3XFOch5ma
>>703
処理結果の反映にInvoke使うんなら不要でしょ
2020/01/05(日) 22:43:52.66ID:kO8WyPRk0
>>704
ボタンの連打対策が必要とか、普通にプログラム書いてる人ならわかると思うんだけど
2020/01/05(日) 22:53:53.05ID:3XFOch5ma
>>705
だからInvokeでできるよそれ
Runから戻る必要はない
2020/01/05(日) 23:03:25.02ID:3XFOch5ma
もしかして705はBeginInvokeと勘違いしてるんだろうか
InvokeはUIスレッド上で実際に処理が完了するまで呼出元のスレッドをブロックするから、連打対策のような用途にも使えるんだよ
なぜかコピペサイトではBeginInvokeだけ紹介されてることが多くて、意外とInvokeの方は知られてなかったりするんだよね
よく理解しないで使ってデッドロックさせるアホがいるからかな
708デフォルトの名無しさん (アウアウウー Saa5-CnQr)
垢版 |
2020/01/05(日) 23:09:20.18ID:MI3jwdk/a
何を争ってるのかよく分からんけど、連打対策になるって主張もよく分かんないねw
2020/01/05(日) 23:12:07.22ID:3XFOch5ma
いや、そもそも処理終了後にEnabledを戻すだけならBeginInvokeでもいいか
細かいことを言えばInvoke/BeginInvokeだと一度メッセージループに処理が返ってしまい連打を防ぎきれない可能性があるから
無効化の方はRunの前にやっておく方がベターだけど、いずれにせよ後続処理はRunの中からInvoke/BeginInvokeで問題ないね
(というか振る舞いは等価)
2020/01/05(日) 23:13:02.39ID:XwlRh/tg0
継続ブロックがUIスレッドに戻ってくるからInvoke不要ってのがasyncイベントハンドラの価値じゃねえのん
逆にメリットそれだけだからTaskに包んで書こうが構わんやろって向きもあるんだろうけど

マそもそも同期コンテキストの前提がおけないライブラリ内のコードでは
継続ブロックがどのスレッドで動き出すかわからないなんてことも普通にあるので
ConfigureAwaitとか必要悪ともお付き合いせにゃならんのが辛いところネー
711デフォルトの名無しさん (ワッチョイ 7197-IH4P)
垢版 |
2020/01/05(日) 23:19:25.32ID:dqyEtfEv0
>>706
それはTaskだけでなんでも出来るからawaitなんかいらないよ言ってることにならない?
もちろんInvoke使えばできるだろうけど、アニメーションなんかが絡むとコールバックだらけになりそうな気がする。

Task.Runの中のInvokeにはプログレスバーを進める、テキストエリアにテキストログを出す、
みたいなあまり本質的でないUIの変更にとどめておいて、本格的な処理結果の表示はawait以降に書く、なんてのも
コードの読みやすさの確保のためには有効な手順じゃないかな。自分はそうしてる。
2020/01/06(月) 00:46:28.60ID:3wPOSvMe0
>>709
実際にそんなソース書くようなやつはセンス無いから、営業や総務に異動させるわ
2020/01/06(月) 18:16:42.26ID:Qm/elW020
ファイルサーバにC#のサービスを常駐させてクライアントからリクエスト受けたらdosコマンドを実行したいのですがどういう技術で実現出来るでしょうか?
単純にサービスだとリクエストをどう受ければ良いのだろうと悩んでおります
2020/01/06(月) 18:26:36.55ID:+ezJCAApM
そんなもんApacheでも立ててCGIでええやろ
C#なんぞ要らん
2020/01/06(月) 18:33:44.24ID:Qm/elW020
昔なんですけどwebサーバ立てないでリクエスト受け付けるサービス作ってた人が居たんです
そんなこと出来るんだと思った数年後の現在調べてみても何の技術か解らず
C#で作られていたのは覚えてるのですが
2020/01/06(月) 18:38:57.81ID:X36Zclkj0
サービス作った人にやり方を聞けばいいのでは
717デフォルトの名無しさん (ワッチョイ 42ad-f3Fz)
垢版 |
2020/01/06(月) 18:42:12.36ID:HrPzlOWn0
>>713
https://dobon.net/vb/dotnet/internet/tcpclientserver.html
ソケットで受けてProcess.Startとかすればいけると思うけどあまりお勧めしない
2020/01/06(月) 18:48:18.84ID:sG64rza2M
System.Net.HttpListenerのこと言ってる?
2020/01/06(月) 21:20:55.59ID:/c/Em2OW0
>>715
TcpListener/TcpClientでSocketをそのまま使うかWCFかな
2020/01/06(月) 21:47:44.44ID:78RinjQr0
>>713
どうやって実現するかを考える前に
解決したい問題を定義することからはじめたほうがいい
そうしないと適切な選択肢を発見できない可能性が高いから

このケースで問題の定義ってのは
「どういう処理を、どういう理由で、どういう制約の中で実行したいのか」
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況