0

私は Windows ストア (C++) アプリに取り組んでいます。Webサービスを利用してデータベースから読み込む方法です。

task<std::wstring> Ternet::GetFromDB(cancellation_token cancellationToken)
{
    uriString = ref new String(L"http://myHost:1234/RestServiceImpl.svc/attempt");
    auto uri = ref new Windows::Foundation::Uri(Helpers::Trim(uriString));
    cancellationTokenSource = cancellation_token_source();
    return httpRequest.GetAsync(uri, cancellationTokenSource.get_token()).then([this](task<std::wstring> response)->std::wstring
    {
        try
        {
            Windows::UI::Popups::MessageDialog wMsg(ref new String(response.get().c_str()), "success");
            wMsg.ShowAsync();
            return response.get();
        }
        catch (const task_canceled&)
        {
            Windows::UI::Popups::MessageDialog wMsg("Couldn't load content. Check internet connectivity.", "Error");
            wMsg.ShowAsync();
            std::wstring abc;
            return abc;
        }
        catch (Exception^ ex)
        {
            Windows::UI::Popups::MessageDialog wMsg("Couldn't load content. Check internet connectivity.", "Error");
            wMsg.ShowAsync();
            std::wstring abc;
            return abc;
        }
    } , task_continuation_context::use_current());
}

受信したデータを呼び出し元の関数に返す方法がわかりません。今、私は次のようにデータクラスのコンストラクターでこの関数を呼び出しています:

ternet.GetFromDB(cancellationTokenSource.get_token()).then([this](task<std::wstring> response)
{
    data = ref new String(response.get().c_str());
});

GetFromDB() から返されたデータを受信しようとすると、常に COM 例外が発生します。しかし、これはうまくいきます:

ternet.GetFromDB(cancellationTokenSource.get_token());

GetFromDB の完了を他のコードにチェーンするより良い方法を提案してください。そして、 GetFromDB() の try{} ブロック内から戻り値を取得する方法。私は非同期プログラミングの非常に新しい学生であることを覚えておいてください。

4

1 に答える 1

0

への呼び出しの継続がGetFromDBUI スレッドで発生している場合 (貼り付けた呼び出しサイトが UI スレッドで発生していると仮定すると、デフォルトでそうなると思います)、get()返されたを呼び出すtaskと例外がスローされます。タスクが完了するのを待っている UI スレッドをブロックすることはできません。

2 つの提案。どちらもその問題を解決するはずです。1 つ目は関係なく動作するはずですが、2 つ目は、UI スレッドへの応答文字列を取得しようとしていない場合 (表示など) にのみ適しています。

1) 継続 ( に渡すラムダ) を記述してthen、前のタスク自体ではなく、前のタスクの実際の結果を受け取るようにします。言い換えれば、これを書く代わりに:

ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... });

これを書きます:

ternet.GetFromDB(...).then([this](std::wstring response) { ... });

後者との違いは、継続機構がget()(バックグラウンド スレッドで) 呼び出しを行い、結果を継続関数に渡すことです。これは全体的にはるかに簡単です。タスクが実行されたときにスローされた可能性のある例外をキャッチしたい場合は、継続に実際のタスクを引数として取る必要があるだけです。

2)バックグラウンド/任意のスレッドで継続を実行するように指示します:

ternet.GetFromDB(...).then([this](task<std::wstring> response) { ... }, task_continuation_context::use_arbitrary());

バックグラウンド スレッドをブロックするかどうかは気にしません。UI スレッドで呼び出すかどうかだけを気get()にします。

于 2013-07-18T16:17:13.233 に答える