2017-08-09 31 views
3

私のHttpClientは、ダイジェスト認証を使用してサーバーに接続し、応答として検索クエリを期待しています。これらの検索クエリはいつでも入力できるため、クライアントはいつでも接続を開いたままにすることが期待されます。タイムアウトが無限のHttpClientがタイムアウト例外をスローする

接続は、以下のコードを使用して行われる。

public static async void ListenForSearchQueries(int resourceId) 
{ 
    var url = $"xxx/yyy/{resourceId}/waitForSearchRequest?token=abc"; 

    var httpHandler = new HttpClientHandler { PreAuthenticate = true }; 

    using (var digestAuthMessageHandler = new DigestAuthMessageHandler(httpHandler, "user", "password")) 
    using (var client = new HttpClient(digestAuthMessageHandler)) 
    { 
     client.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite); 

     var request = new HttpRequestMessage(HttpMethod.Get, url); 

     var tokenSource = new CancellationTokenSource(); 
      tokenSource.CancelAfter(TimeSpan.FromMilliseconds(Timeout.Infinite)); 

     using (var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, tokenSource.Token)) 
     { 
      Console.WriteLine("\nResponse code: " + response.StatusCode); 

      using (var body = await response.Content.ReadAsStreamAsync()) 
      using (var reader = new StreamReader(body)) 
       while (!reader.EndOfStream) 
        Console.WriteLine(reader.ReadLine()); 
     } 
    } 
} 

これは、方法は、コンソールアプリケーションのメインの方法で使用されている方法です。

private static void Main(string[] args) 
{ 
    const int serviceId = 128; 
    . 
    . 
    . 
    ListenForSearchQueries(resourceId); 
    Console.ReadKey(); 
} 

これは、コンソールウィンドウの出力は次のようになります。クライアントのタイムアウトは、接続時間がされていない5分(後におおよそアウト、無限大に設定されていても

Response code: OK 
--searchRequestBoundary 

最初の出力後にHttpClientのデフォルトのタイムアウト)を返します。次の例外がスローされます。 DelegateHandler認証に使用

System.IO.IOException occurred 
    HResult=0x80131620 
    Message=The read operation failed, see inner exception. 
    Source=System.Net.Http 
    StackTrace: 
    at System.Net.Http.HttpClientHandler.WebExceptionWrapperStream.Read(Byte[] buffer, Int32 offset, Int32 count) 
    at System.Net.Http.DelegatingStream.Read(Byte[] buffer, Int32 offset, Int32 count) 
    at System.IO.StreamReader.ReadBuffer() 
    at System.IO.StreamReader.get_EndOfStream() 
    at ConsoleTester.Program.<ListenSearchQueriesDigestAuthMessageHandler>d__10.MoveNext() in C:\Users\xyz\ProjName\ConsoleTester\Program.cs:line 270 

Inner Exception 1: 
WebException: The operation has timed out. 

(ソースの項を参照)thisコードの粗い適応です。

なぜクライアントがタイムアウトするのですか?これを防ぐにはどうすればよいですか?

私の究極の目標は、電話をかけて無期限に応答することです。応答が来るとき、私は将来、より多くの応答が来る可能性があるので、接続を終了したくありません。残念ながら、私はサーバー側で何も変更することはできません。

+1

'async void'を使わないでください。このメソッドは 'Task'で定義する必要があります。また、このメソッドがどのように呼び出されているかを示します。 – Nkosi

+1

これは[XY問題](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)のようです。あなたが達成しようとしている究極の目標は何ですか? – Nkosi

+0

@Nkosiこのメソッドは、コンソールアプリケーションのmainメソッドで次のように呼び出されます: 'ListenForSearchQueries(resourceId); Console.ReadKey(); ' –

答えて

1

このストリームのデフォルトの読み取りと書き込みタイムアウトは、is 5 minutesです。これは、5分間の非アクティビティ後にストリームが例外をスローします。この質問に示されている例外と非常によく似ています。

この動作を変更するには、ストリームのReadTimeoutおよび/またはWriteTimeoutプロパティを調整できます。

以下は、ReadTimeoutをInfiniteに変更するListenForSearchQueriesメソッドの修正版です。

実際にストリームによってスローされたが、HttpClientによってスローされたように見える例外が修正されました。

2

は、メソッドが完了するまでにTaskWaitTask

public static async Task ListenForSearchQueries(int resourceId) { 
    //...code removed for brevity 
} 

更新コンソールのmainメソッドを返してください。 response.Content.ReadAsStreamAsync()経由でストリームを返すStream.CanTimeoutis false、デフォルト値はCanTimeoutプロパティがtrueを返すストリームを与えるが

public static void Main(string[] args) { 
    const int serviceId = 128; 
    . 
    . 
    . 
    ListenForSearchQueries(resourceId).Wait(); 
    Console.ReadKey(); 
} 
+0

残念ながら、この問題は同じ例外メッセージでも続きます。 –

+0

@AliZahid私は好奇心が強いです。なぜHttpClientを使用してクエリをリッスンしていますか?もう一度私はこれがXY問題であることを参照します。 – Nkosi

+0

私は基本的に呼び出しを行い、応答を無期限に待っています。私はまた、将来応答が増える可能性があるため、応答が来たときに接続を閉じることを望んでいません。残念ながらサーバー側では何も変更できません。 –

関連する問題