C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

HttpClientのPostAsyncにて落ちる

[トピック内 10 記事 (1 - 10 表示)]  << 0 >>

■89643 / inTopicNo.1)  HttpClientのPostAsyncにて落ちる
  
□投稿者/ S (1回)-(2018/12/12(Wed) 14:22:26)

分類:[C#] 

2018/12/12(Wed) 14:58:47 編集(投稿者)

下記のようなコードで、例外のキャッチすらできず落ちる(コンソールアプリケーションが落ちる)のは、
どのような原因が考えられるのでしょうか?

Framework 4.6.1

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

HttpClient hcClient = new HttpClient();
hcClient.Timeout = Timeout.InfiniteTimeSpan;
hcClient.DefaultRequestHeaders.Add("Accept", "application/xml");
hcClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ESA", "認証パスワード");

StringContent sContent = new StringContent("XMLデータ");

var res = await hcClient.PostAsync("エンドポイントURL", sContent); <----ここで問答無用で落ちる
引用返信 編集キー/
■89653 / inTopicNo.2)  Re[1]: HttpClientのPostAsyncにて落ちる
□投稿者/ S (2回)-(2018/12/13(Thu) 10:53:20)
2018/12/13(Thu) 10:54:08 編集(投稿者)
新規プロジェクトを作成(コンソールアプリケーション)し、以下のようなコードを書いたGETでもGetAsyncにてプチリと落ちます。

using System;
using System.Net;
using System.Net.Http;

namespace httpclient_test
{
    class Program
    {
        static void Main(string[] args)
        {
            test();
        }

        private static async void test()
        {
            try
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
                using (HttpClient hcClient = new HttpClient())
                {
                    var res = await hcClient.GetAsync("https://www.yahoo.co.jp/");


                    string strRes = await res.Content.ReadAsStringAsync();
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
                throw;
            }


        }
    }
}

引用返信 編集キー/
■89654 / inTopicNo.3)  Re[2]: HttpClientのPostAsyncにて落ちる
□投稿者/ 魔界の仮面弁士 (1988回)-(2018/12/13(Thu) 11:02:33)
No89653 (S さん) に返信
> 新規プロジェクトを作成(コンソールアプリケーション)し、以下のようなコードを書いたGETでもGetAsyncにてプチリと落ちます。

メインスレッド が終了したことにより、アプリケーション ドメインがアンロードされているのでは?


using System;
using System.Net;
using System.Net.Http;

namespace httpclient_test
{
  class Program
  {
    static void Main(string[] args)
    {
      test();
      Console.ReadLine(); // ★これを追加
    }

    private static async void test()
    {
      try
      {
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
        using (HttpClient hcClient = new HttpClient())
        {
          var res = await hcClient.GetAsync("https://www.yahoo.co.jp/");

          string strRes = await res.Content.ReadAsStringAsync();
          Console.WriteLine(strRes); // ★確認用にこれも追加
        }
      }
      catch (System.Exception ex)
      {
        Console.WriteLine(ex.StackTrace);
        throw;
      }
    }
  }
}
引用返信 編集キー/
■89656 / inTopicNo.4)  Re[3]: HttpClientのPostAsyncにて落ちる
□投稿者/ S (3回)-(2018/12/13(Thu) 11:24:07)
2018/12/13(Thu) 11:24:36 編集(投稿者)
No89654 (魔界の仮面弁士 さん) に返信
> ■No89653 (S さん) に返信
>>新規プロジェクトを作成(コンソールアプリケーション)し、以下のようなコードを書いたGETでもGetAsyncにてプチリと落ちます。
> 
> メインスレッド が終了したことにより、アプリケーション ドメインがアンロードされているのでは?

あぁ、魔界の仮面弁士さんの言う通りでした。
ありがとうございます。
Mainにて待つには、以下のように書けばOKですか?
試して見た限りでは、大丈夫そうでした。
(現在使用のバージョンでは、Mainにasync付けられないので)

using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace httpclient_test
{
    class Program
    {
        static void Main(string[] args)
        {
            test().Wait();
        }

        private static async Task test()
        {
            try
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
                using (HttpClient hcClient = new HttpClient())
                {
                    var res = await hcClient.GetAsync("https://www.yahoo.co.jp/");

                    string strRes = await res.Content.ReadAsStringAsync();
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.StackTrace);
                throw;
            }
        }
    }
}

引用返信 編集キー/
■89658 / inTopicNo.5)  Re[4]: HttpClientのPostAsyncにて落ちる
□投稿者/ WebSurfer (1706回)-(2018/12/13(Thu) 11:52:21)
No89656 (S さん) に返信

> Mainにて待つには、以下のように書けばOKですか?

Microsoft の記事(URL 下記)では以下のようにしています。

test().GetAwaiter().GetResult();

Call a Web API From a .NET Client (C#)
https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

実際自分のアプリで試して OK でした。

HttpClient で WCF サービスを呼出
http://surferonwww.info/BlogEngine/post/2018/02/24/request-wcf-service-using-httpclient.aspx
引用返信 編集キー/
■89660 / inTopicNo.6)  Re[4]: HttpClientのPostAsyncにて落ちる
□投稿者/ 魔界の仮面弁士 (1989回)-(2018/12/13(Thu) 13:06:58)
No89656 (S さん) に返信
> (現在使用のバージョンでは、Mainにasync付けられないので)
非同期 Main は C# 7.1 からですね。
Visual Studio 2017 だと v15.3 以降が必要。


> Mainにて待つには、以下のように書けばOKですか?
> private static async Task test()

戻り値に関しては、async void の利用は避け、
async Task とする方が望ましいですね。

https://msdn.microsoft.com/ja-jp/magazine/jj991977.aspx
|
| 《async void を避ける》
| 使用できる戻り値の型には、Task、Task<T>、および void の 3 つがありますが、
| async メソッドで自然な戻り値の型は Task と Task<T> だけです。
|
| 《すべて非同期にする》
| 「すべて非同期にする」とは、結果をよく考えずに
| 同期コードと非同期コードを混在させるべきではないことを表しています。
| 特に、Task.Wait または Task.Result を呼び出して
| 非同期コードでブロックするのは通常適切な考え方ではありません。
| 非同期プログラミングを試しているプログラマーが特に陥りやすい問題で、
| アプリケーションのごく一部だけを非同期に変換し、それを同期 API でラップし、
| アプリケーションの残りの部分が変更の影響を受けないようにしているような場合です。
| 残念ながら、これらはデッドロックの問題を生じます。
|


併せてこちらも参考に。
http://gooner.hateblo.jp/entry/2015/10/27/httpclient/
https://qiita.com/takutoy/items/d45aa736ced25a8158b3
引用返信 編集キー/
■89662 / inTopicNo.7)  Re[5]: HttpClientのPostAsyncにて落ちる
□投稿者/ S (4回)-(2018/12/13(Thu) 13:10:15)
No89658 (WebSurfer さん) に返信

返信、ありがとうございます。

> test().GetAwaiter().GetResult();


特段戻り値が不要な場合でも、GetResult()にしたほうが良いのでしょうか?


引用返信 編集キー/
■89663 / inTopicNo.8)  Re[5]: HttpClientのPostAsyncにて落ちる
□投稿者/ S (5回)-(2018/12/13(Thu) 13:30:22)
No89660 (魔界の仮面弁士 さん) に返信

> https://msdn.microsoft.com/ja-jp/magazine/jj991977.aspx

デッドロックについては、完全ではありませんが理解しました(多分)。
あと、GUI(ASP.NET)とConsoleのコンテキストの処理の違いがあることも上記に書かれていたので、
助かりました。
ありがとうございます。


今回の自分のコンソールアプリケーションでは、上記URLに書かれている、
下記のコードのように書き直したので、今回の質問を解決とします。
ありがとうございました。

図 4 Task.Wait または Task.Result を呼び出す場合がある Main メソッド
class Program
{
  static void Main()
  {
    MainAsync().Wait();
  }
  static async Task MainAsync()
  {
    try
    {
      // Asynchronous implementation.
      await Task.Delay(1000);
    }
    catch (Exception ex)
    {
      // Handle exceptions.
    }
  }
}

引用返信 編集キー/
■89664 / inTopicNo.9)  Re[6]: HttpClientのPostAsyncにて落ちる
□投稿者/ WebSurfer (1707回)-(2018/12/13(Thu) 14:46:59)
No89662 (S さん) に返信

> 特段戻り値が不要な場合でも、GetResult()にしたほうが良いのでしょうか?

そのようです。

以下の記事の「ブロックの裏技」のセクションを見てください。

非同期プログラミング - 非同期への変換
https://msdn.microsoft.com/ja-jp/magazine/mt238404.aspx

"Wait や Result ではなく、GetAwaiter().GetResult を使ってブロックすることをお勧めします。Wait や
Result では、AggregateException 内にすべての例外をラップすることになります。そのため、エラー処理
の複雑さが増します。"
引用返信 編集キー/
■89665 / inTopicNo.10)  Re[7]: HttpClientのPostAsyncにて落ちる
□投稿者/ S (6回)-(2018/12/13(Thu) 15:05:13)
No89664 (WebSurfer さん) に返信

> 非同期プログラミング - 非同期への変換
> https://msdn.microsoft.com/ja-jp/magazine/mt238404.aspx

回答、ありがとうございました。
見てみます。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ