パスワードを忘れた? アカウント作成
14281762 journal
日記

yumeの日記: C#学習 17 Console Adventure#6

日記 by yume

反映したくて待ちきれないので、もう早速やる。

Console Adventure
(ソースコード)

前回より:
(日付的に)先日非同期処理について学び、仮のプログラムで実際に目的の動作を確認できたので、早速反映した。
先日の仮コードより改善?した点は
・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』だ。
前作は最後までクリアしたけど、こっちは難しくて途中で投げていた。

この議論は賞味期限が切れたので、アーカイブ化されています。 新たにコメントを付けることはできません。
typodupeerror

ナニゲにアレゲなのは、ナニゲなアレゲ -- アレゲ研究家

読み込み中...