yumeの日記: C#学習 17 Console Adventure#6
反映したくて待ちきれないので、もう早速やる。
前回より:
(日付的に)先日非同期処理について学び、仮のプログラムで実際に目的の動作を確認できたので、早速反映した。
先日の仮コードより改善?した点は
・System.Threading.Thread.Sleep()の代わりにawait Task.Delay()を使った(その方がいいらしい。我ながら雑な理由だが)
・Console.ReadKey()をConsole.ReadKey(true)にした(入力した文字が表示されなくなった)
初めは全く想定外の概念だったので、これを無事に組み込めるか全く不安だったが、実際に書いてみると驚くほどあっさりと終わった。
やったことといえば
・enum GameStats statを作る(ゲームの状態を示す)
・UserInputKey関数を作る(ReadKeyするたびstatを確認・切り替える)
・TextSpeechをasync関数にして、statに応じてゆっくり喋ったり、全文表示する
だけであった。これもひとえにはTask、async、awaitという簡潔な書き方のおかげだろう。
いまだにちゃんと理解できているかは怪しいが……。とにかくなんとなく理解できたことといえば
・Task.Run(() => メソッド());すると非同期処理が始まる(ここで二手に分かれよう)
・メインスレッドはその次の行に躊躇なく進む
・処理によってはメインスレッドは入力待ちクンにしておけばよい
・awaitヨクワカラナイ
>ちょっと不安になってきたな……。
検索すると「await Task.Run(()……」と書いてるものが多い。
qiita @acple@github曰く、
・Taskはただのタスク(!?)
・asyncはメソッドの中でawaitを使えるようにする。だけ。
・awaitは「指定したTaskの完了を待つ」「その結果を取り出す」
>ん~、ということは
await Task.Run(()~略~処理A();
処理B();
とすると:
・サブに分けた処理Aの結果を待つ
・その後処理Bをやる
ということ? だとしたらそれは普通に同期処理と同じなようだね。
ちょっと試してみる
class Program
void Main()
{
testMethod();
Console.ReadKey(true);
}
async void testMethod()
{
//こっからはサブスレッド
await Task.Run(() =>
{
for (int i = 0; i < 3; ++i)
{
Console.WriteLine("HO");
Thread.Sleep(50);
}
});
//こっからはメインスレッド
for (int i = 0; i < 3; ++i)
{
Console.WriteLine("GEEEEE");
Thread.Sleep(50);
}
}
出力結果:
HO
HO
HO
GEEEE
GEEEE
GEEEE
ただし、途中でキー入力するとすぐ終了。
やはりawait中の命令が終わったあとにその後の命令が動いている。
ただ、ちょっと予想と違ったのは、Main関数でReadKeyを入れてやらないと「何も出力せずに」プログラムが終了しちゃったこと。
なんとなく、awaitを入れようが入れまいが「こっからはメインスレッド」のところは絶対に処理されるものだと予想していたけど、
実際にはasyncな「testMethod」を実行した時点で、もうすでに二手にわかれてる?
ということは、もっとシンプルに
static void Main()
{
Douki();
Sonota();
}
async void Douki()
{
await Task.Run(() =>
{
//do something
});
}
みたいな感じで、DoukiとSonotaを同時に動かしたりできるわけか。実際動く。
あ、いや、でも、じゃあ
static void Main()
{
Task.Run(() => Douki());
Sonota();
}
でいいのでは……ってこれ今回書いたやつがだいたいそうだった。
寝よ……。
--
あとちょっと気になったのは、二手に分かれた後、サブスレッドの仕事を終えて、そのあと何もしなくてよいんだろうか(破棄とか?)。
感覚的には、スレッドを分けた(二つ目のスレッドを呼び出した)あとに、仕事が終わったスレッドはその場に待機し続けているイメージである。
teratail @Zuishin曰く、
・WaitHandleを使わなければ不要
だそうだ。
--どうでもいいこと
マルチスレッドについて考えているうちに気付いたけど、
これって『7 Billion Humans』だ。
前作は最後までクリアしたけど、こっちは難しくて途中で投げていた。
C#学習 17 Console Adventure#6 More ログイン