Task にパラメータを渡す

Task にパラメータを渡します。

前田稔の超初心者のプログラム入門

プログラムの説明

  1. Task を関数として定義して、パラメータを渡します。
    Main.cpp を次のように修正します。
    #include <ppltasks.h>
    #include <string>
    #include <windows.h>
    
    using namespace concurrency;
    using namespace std;
    
    task<wstring> Time(DWORD tim)
    {
        wchar_t str[40];
        int ss,ms;
        ms = tim;
        ss = ms / 1000;
        ms = ms % 1000;
        ss = ss % 60;
        swprintf(str, 40, L"%d:%d", ss, ms);
        auto s = make_shared<wstring>(str);
        return create_task([s]
        {
            wstring str;
            str = L"Time= " + *s + L"\n";
            return str;
        });
    }
    int wmain()
    {
        wstring str;
        auto t = Time(GetTickCount());
        str = L"Start Time: " + t.get() + L"\n";
        OutputDebugString(str.data());
    
        Sleep((rand() % 100)+500);
        t = Time(GetTickCount());
        str = L"End Time: " + t.get() + L"\n";
        OutputDebugString(str.data());
    }
    
  2. task<wstring> Time(DWORD tim) がタスクで実行される関数の定義です。
    auto t = Time(GetTickCount()); で呼び出されます。
  3. wmain() から Task で定義した Time() 関数にタイムスタンプ GetTickCount() を渡して「秒:ミリ秒」の形式で印字します。
    GetTickCount() の値は 0 ミリ秒から 2^32 ミリ秒(約 49.71 日)の間を循環します。
    一度目のタイムスタンプから Sleep((rand() % 100)+500); の間隔を置いて二度目のタイムスタンプを印字します。
  4. 渡された DWORD tim からミリ秒の値を ms に、秒の値を ss に取得します。
        ms = tim;
        ss = ms / 1000;
        ms = ms % 1000;
        ss = ss % 60;
    
  5. 秒とミリ秒を str に編集して、auto s に設定します。
    make_shared は <タイプ> の型に合わせて値を設定する関数です。
    create_task([s] でタスクを定義します。
    Task 関数 Time() は return create_task([s] { ・・・ }); の実行結果をリターンします。
  6. Start Time: が一度目の、End Time: が二度目のタイプスタンプです。
    実行する毎に値が変わるので試して下さい。
    Start Time: Time= 35:968
    End Time: Time= 36:500
    

同時に起動

  1. パラメータを変えて、二個の Task を同時に起動します。
    Main.cpp を次のように修正します。
    #include <ppltasks.h>
    #include <string>
    #include <windows.h>
    
    using namespace concurrency;
    using namespace std;
    
    task<int> Time(int rnd, wstring id)
    {
        return create_task([rnd, id]
        {
            DWORD   ms;
            wchar_t str[40];
            for (int i = 0; i < 3; i++)
            {
                ms = GetTickCount();
                swprintf(str, 40, L"%s : Time %d ミリ秒\n", id.data(), ms);
                OutputDebugString(str);
                Sleep(rand() % rnd);
            }
            return 0;
        });
    }
    
    int wmain()
    {
        auto t = Time(200, L"A");
        wchar_t str[40];
        auto t2 = Time(50, L"B");
        swprintf(str, 40, L"終了コード: %d %d\n\n", t.get(), t2.get());
        OutputDebugString(str);
    }
    
  2. Time() 関数のパラメータ int rnd は Sleep() 間隔を調整するための値です。
    return create_task([rnd, id] で Task を設定します。
    Task では rnd を使って間隔を取りながらタイムスタンプを3回印字します。
    Task 関数では、終了を確認するために 0 をリターンしています。
  3. wmain() では task<int> Time 関数に Sleep() 間隔を調整する rnd と識別する id を渡して、二回 Task を起動します。
    auto t2 = Time(50, L"B"); は後から起動されますが rnd が 50 なので先に印字が終わります。
    swprintf(str, 40, L"終了コード: %d %d\n\n", t.get(), t2.get()); で Task の終了を待って印字します。
  4. 実行結果です。
    A と B が同時に実行され、後から起動した B の方が先に印字が終わっています。
    A : Time 24580625 ミリ秒
    B : Time 24580625 ミリ秒
    A : Time 24580687 ミリ秒
    B : Time 24580687 ミリ秒
    B : Time 24580718 ミリ秒
    A : Time 24580750 ミリ秒
    終了コード: 0 0
    

void の待ち合わせ

  1. Time() 関数を void で定義します。
    二個の Task を同時に起動して待ち合せます。
    Main.cpp を次のように修正します。
    #include <ppltasks.h>
    #include <string>
    #include <windows.h>
    
    using namespace concurrency;
    using namespace std;
    
    task<void> Time(int rnd, wstring id)
    {
        return create_task([rnd, id]
        {
            DWORD   ms;
            wchar_t str[40];
            for (int i = 0; i < 3; i++)
            {
                ms = GetTickCount();
                swprintf(str, 40, L"%s : Time %d ミリ秒\n", id.data(), ms);
                OutputDebugString(str);
                Sleep(rand() % rnd);
            }
        });
    }
    
    int wmain()
    {
        auto t = Time(200, L"A");
        auto t2 = Time(50, L"B");
        (t && t2).wait();
        OutputDebugString(L"END Task\n"); 
    }
    
  2. int rnd は Sleep() 間隔を調整するための値です。
    return create_task([rnd, id] で Task を設定します。
    Task では rnd を使って間隔を取りながらタイムスタンプを3回印字します。
  3. wmain() では、task<void> Time() 関数に Sleep() 間隔を調整する rnd と識別する id を渡して、二回 Task を起動します。
    auto t2 = Time(50, L"B"); は後から起動されますが rnd が 50 なので先に印字が終わります。
    (t && t2).wait(); で Task の終了を待ち合せます。
  4. 実行結果です。
    A と B が同時に実行され、後から起動した B の方が先に印字が終わっています。
    A : Time 7925515 ミリ秒
    B : Time 7925515 ミリ秒
    B : Time 7925546 ミリ秒
    A : Time 7925546 ミリ秒
    B : Time 7925578 ミリ秒
    A : Time 7925625 ミリ秒
    END Task
    

[Next Chapter ↓] Win10 Task
[Previous Chapter ↑] Task の関数値

超初心者のプログラム入門(C/C++)