質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

2回答

33299閲覧

C#でHTTP通信を行う方法(HttpClientを用いる場合)

alths122

総合スコア16

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

HttpWebRequest

HttpWebRequestとは.NETにおけるクラスであり、WebRequestクラスをHTTPに導入するものです。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2016/05/03 10:50

目的

C#でHTTP通信を行い、その結果を取得したいと思っています。
(最終的にはWeb APIを叩くことが目的です)
資料となるサイトを参考にコードを書いてみたのですが応答が返らず、対処方法が分からないので教えていただきたいです。

実装

まっさらなC#/Formsアプリに、ボタンを一つだけ用意します。
ボタンを押すとWebアクセスを試みるだけのプログラムです。

[フォーム側(ボタンを押すとアクセス)]

C#

1 public partial class MainWindow : Form 2 { 3 public MainWindow() 4 { 5 InitializeComponent(); 6 } 7 8 private void btnRequest_Click(object sender, EventArgs e) 9 { 10 Uri uri = new Uri("http://www.google.com"); 11 // ここでwebアクセスを行う 12 Task<string> webTask = WebConn.GetApiAsync(uri); 13 string result = webTask.Result; 14 Console.WriteLine(result); 15 } 16 }

[アクセス処理(WebConn)]

C#

1 public class WebConn 2 { 3 public static async Task<string> GetApiAsync(Uri uri) 4 { 5 using (HttpClient client = new HttpClient()) 6 { 7 // ヘッダ情報設定 8 client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko"); 9 client.DefaultRequestHeaders.Add("Accept-Language", "ja-JP"); 10 client.Timeout = TimeSpan.FromSeconds(5.0); 11 12 try 13 { 14 // 実際のアクセス処理はここだけ 15 string res = await client.GetStringAsync(uri); 16 // ここに辿りつけない 17 return res; 18 } catch(HttpRequestException e) 19 { 20 // 例外処理(省略) 21 } 22 return null; 23 } 24 } 25 }

発生している問題

上記のコードを実行しフォームに用意したボタンを押したところ、ウィンドウが操作を受け付けない状態になります。
具体的には、上記コード(アクセス処理)の
string res = await client.GetStringAsync(uri); を実行した後、次の return res;に辿り着きません。
また、実行時に例外が発生することもありません。

参考資料

@ITの記事
http://www.atmarkit.co.jp/ait/articles/1501/06/news086.html
に掲載されているコードを、ほぼ流用しています。

その他

C#を用いて通信を行うのは初めてです。
もしHttpClient使うより良い方法があれば教えてください。
(ところでteratailでは、C#のコードはシンタックスハイライトされないのでしょうか…?)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

C#

1 2public partial class MainWindow : Form 3{ 4 public MainWindow() 5 { 6 InitializeComponent(); 7 } 8 // await するために async 宣言を追加 9 private async void btnRequest_Click(object sender, EventArgs e) 10 { 11 Uri uri = new Uri("http://www.google.com"); 12 // ここでwebアクセスを行う 13 // 非同期にするために await 宣言を追加 14 Task<string> webTask = await WebConn.GetApiAsync(uri); 15 string result = webTask.Result; 16 Console.WriteLine(result); 17 } 18}

このようにしたら動きそうな予感が。

(参考)Async および Await を使用した非同期プログラミング (C# および Visual Basic)

###(追記)動作検証済みサンプルコード

C#

1using System; 2using System.Threading.Tasks; 3using System.Windows.Forms; 4using System.Diagnostics; 5using System.Net.Http; 6 7namespace AsyncTest 8{ 9 public partial class Form1 : Form 10 { 11 public Form1() 12 { 13 InitializeComponent(); 14 } 15 16 private async void button1_Click(object sender, EventArgs e) 17 { 18 Debug.WriteLine("Clicked!"); 19 string s = await WebConn.GetApiAsync(); 20 Debug.WriteLine("check 3, len = " + s.Length); 21 } 22 } 23 24 public class WebConn 25 { 26 public static async Task<string> GetApiAsync() 27 { 28 using (HttpClient client = new HttpClient()) 29 { 30 Debug.WriteLine("check 1"); 31 string urlContents = await client.GetStringAsync("http://msdn.microsoft.com"); 32 Debug.WriteLine("check 2"); 33 return urlContents; 34 } 35 } 36 } 37} 38

Form1は、空のWindowsフォームに、ボタンを一つ貼り付け打だけのものです。
OS:Windows 10 (10.0.10586)
VS: Visual Studio 2015
.NetFramework: 4.5

上記のコードで、コンパイルエラー、実行エラーともに発生せず、期待通りの動作ができることを確認しました。

ご参考になれば。

投稿2016/05/03 13:54

編集2016/05/04 04:23
tkanda

総合スコア2425

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

alths122

2016/05/03 14:06

ありがとうございます。 実のところ、この方法も下で挙げたスライドに書いてあったのですが、 この方法だと何故か `await WebConn.GetApiAsync(uri)` の箇所で `型 'string' を 'System.Threading.Tasks.Task<string>' に暗黙的に変換できません`と言われてしまいます。 どう見ても`WebConn.GetApiAsync()`はstringを返す実装ではないと思うのですが、awaitを付けると、暗黙的にstringを返すような処理に変更でもされるのでしょうか…?
tkanda

2016/05/04 04:24

ビルドエラーが発生する原因はわかりませんが、こちらで動作検証してみましたので、そのソースコードを追記しました。ご自身の実際のコードと見比べてみてください。
guest

0

自己解決しました。
以下サイトのスライド 29~35ページの内容と同じ問題でした。

HttpClient詳解、或いは非同期の落とし穴について
http://www.slideshare.net/neuecc/httpclient

awaitにより待機のデッドロックが発生しておりました。
今回は、await client.GetStringAsync(uri)
await client.GetStringAsync(uri).ConfigureAwait(false)に変更することで解決しました。

投稿2016/05/03 13:21

alths122

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問