放浪軍師のアプリ開発局

VTuberみたいなアプリケーション夏狂乱など、自由気ままにアプリを開発したりしています。他にもいろいろやってます。尚、このブログはわからないところを頑張って解決するブログであるため、正しい保証がありません。ご注意ください。

乱ちゃんProjectその4(非同期処理)

放浪軍師のXamarin.Formsによるアプリ開発
ちょっと間が空いてしまいました。やっぱ年度末は辛いやね!
とりあえず今回は、前回ルーレット化に失敗したのでそこを修正するよ!
まず、初めて訪問された方は以下をお読みください。

www.gunshi.info

非同期処理

今回の件について、twitterやコメント欄にてご指摘を賜りました。すげーありがたいことで御座います。
…で、前回ルーレット化に失敗した原因は非同期処理が出来ていないからではないか?というご指摘を複数受けて色々と調べてみました。

まず、非同期処理とは何か?についてですが、これに関しては前回予想した以下の内容が当たらずとも遠からずだったようす。

多分ですがSingenLabel = r1.RandomValue;でラベルの値を更新してはいますが、それがデータバインディングによってViewに反映するのはGetRandomCommand()を抜けた後とかになるんじゃなかろうか?

実際は
【一つのコード(スレッドと言うらしい)が走り出したらそれが終わるまで他の処理を行えない】
という事だったようです。

…で、それを回避するための処理が非同期処理
表示に関するスレッドを、現在走っているスレッドとは別のスレッドとする事により、並列処理が可能になり、結果、今回で言うところのループ処理と表示処理を同時にこなすことができるようになる。…って事らしい。

まぁ俺の言葉で説明したところでわからないと思うんで、以下ブログで学ぶと良いと思います。KOUJI MATSUI さんの記事です。
www.kekyo.net

で、修正したコードがこちらになります。 kohzy99さんのコメントそのままで恐縮です…。

/// <summary>
/// 進言コマンドを取得する
/// </summary>
private async void GetRandomCommand()
{
    //数字を範囲指定
    RandomData r1;
    r1 = new RandomData(1, 3);

    int loopNo = 10; //ループ回数(回)
    int loopTime = 1000; //ループ時間(msec)

    //基準となるウェイト時間(msec)
    float oneWaitTime = loopTime / (((loopNo - 1) * loopNo) / 2);

    for (int i = 1; i <= loopNo; i++)
    {
        r1.SetRandomData();
        SingenLabel = r1.RandomValue;
        if(i < loopNo)
        {
            //少しずつウェイト時間を長くする
            await System.Threading.Tasks.Task.Delay((int)(oneWaitTime * i));
        }
    }

}

GetRandomCommandにasyncを追加。また、Task.Delayにawaitをつけています。この組み合わせで非同期処理を行うのが基本みたいですね。
task.Wait()は不要っぽかったので削除しました。
ループ回数やループ時間は調整してみました。動かしてみた結果はこちら。UWPです。
f:id:roamschemer:20180330000951g:plain:w150
ちゃんとルーレットしてますね!

ただ、このasyncとawaitですが今後確実に重要になる項目であるにも関わらず、俺自身が正しく理解できていない可能性が高いです。なーんかしっくりきていない。kohzy99さんのコメントがなけりゃいまだに彷徨ってたかもしれんです。

先ほど紹介したKOUJI MATSUIさんのブログには非同期処理についてかなり詳しく説明があるので、よく読み漁っておきたいと思います。