2014-09-12 3 views
0

Я использую класс оболочки, который я сделал для HttpClient. Когда я вызываю SendAsync, он выдает исключение, в котором говорится: «Задача была отменена».Почему мой HttpClient.SendAsync отменяется?

Я не понимаю, почему это происходит, я не передаю ему токен отмены, и я использую Await, чтобы дождаться результата перед возвратом. Может ли кто-нибудь помочь?

EDIT 1: Я прочитал, что проблема с HttpClient и использованием в .NET 4.0, если не правильно закодирована. http://forums.asp.net/t/1863442.aspx?HttpClient+Error+A+Task+was+canceled+. Тем не менее, я использую .NET 4.5 и ключевое слово Await, поэтому у меня не должно быть этой проблемы. Кроме того, когда я нажимаю объект HttpClient во время точки останова при броске исключения, он не указывает, что объект удален.

Фрагмент кода из класса HttpClientWrapper, в котором происходит исключение;

Try 
    Return Await Client.SendAsync(Message, HttpCompletionOption.ResponseHeadersRead) 
Catch ex As Exception 
    If DebugMode Then Output(OutputBufferKey, Method.ToString & " " & Url & " " & ex.Message, OutputType.Error) 
End Try 

Пользовательский класс HttpClientWrapper;

Public Class HttpClientWrapper 
    Implements IDisposable 

    Protected Handler As New HttpClientHandler 
    Protected Client As HttpClient = Nothing 

    Public Property OutputBufferKey As String = Nothing 
    Public Property CancellationToken As CancellationToken? = Nothing 

    Public Sub New(Optional Proxy As WebProxy = Nothing, Optional Cookies As CookieContainer = Nothing, Optional UserAgent As String = Nothing, _ 
       Optional OutputBufferKey As String = Nothing, Optional CancellationToken As CancellationToken? = Nothing) 
    Me.OutputBufferKey = OutputBufferKey 
    Me.CancellationToken = CancellationToken 

    If UserAgent Is Nothing Then UserAgent = RandomString(UserAgents) 

    SetCookies(Cookies) 
    SetProxy(Proxy) 

    Handler.AutomaticDecompression = DecompressionMethods.GZip Or DecompressionMethods.Deflate 
    Client = New HttpClient(Handler, True) 

    Client.Timeout = New TimeSpan(DefaultTimeout) 
    Client.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate") 
    Client.DefaultRequestHeaders.Add("Accept-Language", "en-US,en;q=0.5") 
    Client.DefaultRequestHeaders.Add("DNT", "1") 
    Client.DefaultRequestHeaders.Add("User-Agent", UserAgent) 
    End Sub 

    Public Sub New(User As User, Optional OutputBufferKey As String = Nothing, Optional CancellationToken As CancellationToken? = Nothing) 
    Me.New(User.GetProxy, User.Cookies, User.UserAgent, OutputBufferKey, CancellationToken) 
    End Sub 

    Public Sub New(User As User, Task As Task) 
    Me.New(User.GetProxy, User.Cookies, User.UserAgent, Task.OutputBufferKey, Task.CancellationToken.Token) 
    End Sub 

    Public Sub SetTimeout(Value As Integer) 
    Client.Timeout = New TimeSpan(Value) 
    End Sub 

    Private Sub SetCookies(Cookies As CookieContainer) 
    If Cookies Is Nothing Then 
     Handler.UseCookies = False 
    Else 
     Handler.UseCookies = True 
     Handler.CookieContainer = Cookies 
    End If 
    End Sub 

    Private Sub SetProxy(Proxy As WebProxy) 
    If Proxy Is Nothing Then 
     Handler.UseProxy = False 
    Else 
     Handler.UseProxy = True 
     Handler.Proxy = Proxy 
    End If 
    End Sub 

    Public Async Function WebRequestByteAsync(Url As String, Optional RequestMethod As RequestMethod = RequestMethod.GET, Optional Content As Object = Nothing, _ 
               Optional ContentType As ContentType = ContentType.Default, Optional Accept As String = DefaultAcceptString, _ 
               Optional AdditionalHeaders As NameValueCollection = Nothing, Optional Referer As String = Nothing, Optional NoCache As Boolean = False) _ 
            As Tasks.Task(Of Byte()) 
    Using Response As HttpResponseMessage = Await WebRequestAsync(Url, RequestMethod, Content, ContentType, Accept, AdditionalHeaders, Referer, NoCache) 
     If Response IsNot Nothing Then 
     If Response.StatusCode = HttpStatusCode.OK Then 
      Return Await GetResponseByteAsync(Response) 
     Else 
      Output(OutputBufferKey, Url & " did not return OK (200)", OutputType.Error) 
     End If 
     End If 
     Return Nothing 
    End Using 
    End Function 

    Public Async Function WebRequestStringAsync(Url As String, Optional RequestMethod As RequestMethod = RequestMethod.GET, Optional Content As Object = Nothing, _ 
               Optional ContentType As ContentType = ContentType.Default, Optional Accept As String = DefaultAcceptString, _ 
               Optional AdditionalHeaders As NameValueCollection = Nothing, Optional Referer As String = Nothing, Optional NoCache As Boolean = False) _ 
            As Tasks.Task(Of String) 
    Using Response As HttpResponseMessage = Await WebRequestAsync(Url, RequestMethod, Content, ContentType, Accept, AdditionalHeaders, Referer, NoCache) 
     If Response IsNot Nothing Then 
     If Response.StatusCode = HttpStatusCode.OK Then 
      Return Await GetResponseStringAsync(Response) 
     Else 
      Output(OutputBufferKey, Url & " did not return OK (200)", OutputType.Error) 
     End If 
     End If 
     Return Nothing 
    End Using 
    End Function 

    Public Async Function WebRequestAsync(Url As String, Optional RequestMethod As RequestMethod = RequestMethod.GET, Optional Content As Object = Nothing, _ 
               Optional ContentType As ContentType = ContentType.Default, Optional Accept As String = DefaultAcceptString, _ 
               Optional AdditionalHeaders As NameValueCollection = Nothing, Optional Referer As String = Nothing, Optional NoCache As Boolean = False, _ 
               Optional CanBeCancelled As Boolean = True) _ 
            As Tasks.Task(Of HttpResponseMessage) 

    Dim Method As HttpMethod = Nothing 
    Select Case RequestMethod 
     Case Variables.RequestMethod.DELETE : Method = HttpMethod.Delete 
     Case Variables.RequestMethod.GET : Method = HttpMethod.Get 
     Case Variables.RequestMethod.OPTIONS : Method = HttpMethod.Options 
     Case Variables.RequestMethod.POST : Method = HttpMethod.Post 
     Case Variables.RequestMethod.PUT : Method = HttpMethod.Put 
    End Select 

    'prepare message 
    Dim Message As New HttpRequestMessage(Method, Url) 
    Message.Headers.ExpectContinue = False 
    Message.Headers.TryAddWithoutValidation("Accept", Accept) 
    If Referer IsNot Nothing Then Message.Headers.Add("Referer", Referer) 
    If NoCache Then 
     Message.Headers.Add("Pragma", "no-cache") 
     Message.Headers.Add("Cache-Control", "no-cache") 
    End If 
    If AdditionalHeaders IsNot Nothing Then 
     For Each Key In AdditionalHeaders.AllKeys 
     Message.Headers.TryAddWithoutValidation(Key, AdditionalHeaders(Key)) 
     Next 
    End If 

    'set content 
    If Content IsNot Nothing Then 
     Dim ContentTypeString As String = GetEnumDescription(ContentType) 

     Dim ContentBytes As Byte() = Nothing 
     If TypeOf Content Is String Then 
     ContentBytes = Encoding.UTF8.GetBytes(CType(Content, String)) 
     ElseIf TypeOf Content Is Byte() Then 
     ContentBytes = CType(Content, Byte()) 
     ElseIf TypeOf Content Is MultiPartPostData Then 
     Dim MultiPartPostData As MultiPartPostData = CType(Content, MultiPartPostData) 
     ContentBytes = MultiPartPostData.Bytes 
     ContentTypeString += "; boundary=" & MultiPartPostData.Boundary 
     End If 

     Dim ByteArrayContent As New ByteArrayContent(ContentBytes) 
     ByteArrayContent.Headers.Add("Content-Type", ContentTypeString) 
     Message.Content = ByteArrayContent 
    End If 

    'get response 
    Output(OutputBufferKey, RequestMethod.ToString & " " & Url, OutputType.Debug) 

    Try 
     Return Await Client.SendAsync(Message, HttpCompletionOption.ResponseHeadersRead) 
    Catch ex As Exception 
     If DebugMode Then Output(OutputBufferKey, Method.ToString & " " & Url & " " & ex.Message, OutputType.Error) 
    End Try 

    Return Nothing 
    End Function 

    Public Async Function GetResponseByteAsync(Response As HttpResponseMessage) As Tasks.Task(Of Byte()) 
    If Response Is Nothing Then 
     If DebugMode Then Output(OutputBufferKey, "Unable read content from response message: Is nothing", OutputType.Error) 
    Else 
     Try 
     Return Await Response.Content.ReadAsByteArrayAsync 
     Catch ex As Exception 
     If DebugMode Then Output(OutputBufferKey, "Unable read content from " & Response.RequestMessage.RequestUri.ToString & ": " & ex.Message, OutputType.Error) 
     End Try 
    End If 

    Return Nothing 
    End Function 

    Public Async Function GetResponseStringAsync(Response As HttpResponseMessage) As Tasks.Task(Of String) 
    If Response Is Nothing Then 
     If DebugMode Then Output(OutputBufferKey, "Unable read content from response message: Is nothing", OutputType.Error) 
    Else 
     Try 
     Return Await Response.Content.ReadAsStringAsync 
     Catch ex As Exception 
     If DebugMode Then Output(OutputBufferKey, "Unable read content from " & Response.RequestMessage.RequestUri.ToString & ": " & ex.Message, OutputType.Error) 
     End Try 
    End If 

    Return Nothing 
    End Function 

#Region "IDisposable Support" 
    Private disposedValue As Boolean ' To detect redundant calls 

    ' IDisposable 
    Protected Overridable Sub Dispose(disposing As Boolean) 
    If Not Me.disposedValue Then 
     If disposing Then 
     If Client IsNot Nothing Then Client.Dispose() 
     End If 

    End If 
    Me.disposedValue = True 
    End Sub 

    ' This code added by Visual Basic to correctly implement the disposable pattern. 
    Public Sub Dispose() Implements IDisposable.Dispose 
    ' Do not change this code. Put cleanup code in Dispose(disposing As Boolean) above. 
    Dispose(True) 
    GC.SuppressFinalize(Me) 
    End Sub 
#End Region 

End Class 

Основной код;

Module Main 

    Dim ProxyUrl As String = "proxies.txt" 

    Sub main() 
    DebugMode = True 
    OutputToConsole = True 

    Dim Proxies As New ProxyList(ProxyUrl) 

    Try 
     Run(Proxies).GetAwaiter.GetResult() 
    Catch ex As Exception 
     MsgBox(ex.Message) 
    End Try 

    Console.ReadLine() 

    End Sub 

    Public Async Function Run(Proxies As ProxyList) As Tasks.Task 

    Dim Proxy As WebProxy = Await Proxies.GetProxy 

    Using Client As New HttpClientWrapper(Proxy) 

     Dim Response As String = Await Client.WebRequestStringAsync("http://www.google.com") 
     If Response IsNot Nothing Then Console.WriteLine(Response) 

    End Using 

    End Function 

End Module 

ответ

4

HTTPClient говорит задача была отменена при достижении тайм-аут: вы уверены, что вы большой таймаут прийти/веб-служба отвечает своевременно?

+1

Спасибо за то, что указали мне в правильном направлении, я установил тайм-аут с новым TimeSpan (Ticks) с тиками, равными 8000. Я ошибался в тиках за миллисекунды. Задача решена. – iguanaman

+1

круто! Точно так же, как хорошая идея для будущего - это поставило бы лучший вопрос, если бы вы выбрали исключение в вопросе. – Isantipov

+0

Цените совет, но не знаете, что вы имеете в виду. Есть ли простой способ получить все детали исключения, чтобы задать вопрос? – iguanaman

Смежные вопросы