2017-11-22 18 views
0

私はhttpリクエストを行い、失敗するとリクエストを繰り返します。私はインターネットケーブルをコンピュータに接続して再接続してシミュレーションします。ほとんどの場合、私のコードは動作しますが、時にはco_await HttpClient :: PutAsyncは決して完了しません(C++、コルーチン、UWPを使用)

co_await HttpClient :: PutAsync()は決して "返す"または完了しません。

task<Aws::Result> Aws::S3Request::tryExecute() 
{ 
    // content 
    IHttpContent^ httpContent; 
    httpContent = ref new HttpBufferContent(mBufferContent); 
    httpContent->Headers->ContentType = ref new Headers::HttpMediaTypeHeaderValue(ref new String(mContentType.c_str())); 

    std::wstring signature = getSignature(); 

    // client 
    auto filter = ref new ::Filters::HttpBaseProtocolFilter; 
    filter->AllowUI = false; 
    filter->CacheControl->ReadBehavior = Filters::HttpCacheReadBehavior::NoCache; 
    filter->CacheControl->WriteBehavior = Filters::HttpCacheWriteBehavior::NoCache; 
    HttpClient^ httpClient = ref new HttpClient(filter); 
    httpClient->DefaultRequestHeaders->Authorization = ref new Headers::HttpCredentialsHeaderValue(L"AWS", ref new String((mUser.mAccessKey + L":" + signature).c_str())); 
    httpClient->DefaultRequestHeaders->Append(L"Date", ref new String(mDate.c_str())); 
    httpClient->DefaultRequestHeaders->Append(L"x-amz-acl", L"public-read"); 
    httpClient->DefaultRequestHeaders->Append(L"x-amz-security-token", ref new String(mUser.mSessionToken.c_str())); 

    // http req 
    Uri^ uri = ref new Uri(ref new String(mUri.c_str())); 
    HttpResponseMessage^ response; 
    IAsyncOperationWithProgress<HttpResponseMessage^, HttpProgress>^ progress; 
    try 
    { 
     progress = httpClient->PutAsync(uri, httpContent); 
     progress->Progress = ref new AsyncOperationProgressHandler<HttpResponseMessage^, HttpProgress>(
      [this](IAsyncOperationWithProgress<HttpResponseMessage^, HttpProgress>^ pretask, HttpProgress progressInfo) 
     { 
      /*double got = progressInfo.BytesReceived + progressInfo.BytesSent; 
      double total = 0; 
      if (progressInfo.TotalBytesToReceive) 
      total += progressInfo.TotalBytesToReceive->Value; 
      if (progressInfo.TotalBytesToSend) 
      total += progressInfo.TotalBytesToSend->Value; 
      float progress = (total >= 1) ? float(got/total) : 0.0f; 
      debugOut("--- part progress = ", progress); 
      if (mProgress) 
      *mProgress = progress;*/ 
     } 
     ); 
     response = co_await progress; 
     progress = nullptr; 
     if (!response->IsSuccessStatusCode) 
      debugOut("--- http fail error"); 
    } 
    catch (Platform::COMException^) 
    { 
     debugOut("--- http fail nointernet"); 
     progress = nullptr; 
     mResult = NoInternet; 
     mAnswer.clear(); 
     co_return mResult; 
    } 

    // answer 
    mAnswer = response->Content->ToString()->Data(); 
    debugOut(L"--- Http answer=", mAnswer); 
    mResult = response->IsSuccessStatusCode ? Success : Error; 

    co_return mResult; 
} 

それが失敗した場合、tryExecute()が再び呼び出されます。

私のコードは次のようになります。

ところで、IAsyncOperationWithProgressは、私には0%か100%のどちらかしか与えてくれません。私は各要求に5Mバイトのサイズをアップロードします。

+0

ので、これは100%再現問題ではありません「私のコードは動作しますが、時には、ほとんどの時間」?失敗した時代のスペシャルですか?サーバー側でput要求に制約がありましたか? –

+0

おそらくケーブルのプラグを抜いて再接続する時間の10%で、co_waitのPutAsyncは決して「戻る」か完了しません。タイムアウトがありません。 – Morten

答えて

0

これは動作しますが、良い解決策ではありません。

//response = co_await progress; 
for (int timeout = 5*60*100; true; timeout--) 
{ 
    if (progress->Status != AsyncStatus::Started) 
     break; 
    co_await winrt::resume_after(10ms); 
    if (timeout == 0) 
    { 
     debugOut("--- http fail timeout"); 
     mResult = NoInternet; 
     mAnswer.clear(); 
     co_return mResult; 
    } 
} 
response = progress->GetResults(); 
関連する問題