Я использую класс оболочки, который я сделал для 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
Спасибо за то, что указали мне в правильном направлении, я установил тайм-аут с новым TimeSpan (Ticks) с тиками, равными 8000. Я ошибался в тиках за миллисекунды. Задача решена. – iguanaman
круто! Точно так же, как хорошая идея для будущего - это поставило бы лучший вопрос, если бы вы выбрали исключение в вопросе. – Isantipov
Цените совет, но не знаете, что вы имеете в виду. Есть ли простой способ получить все детали исключения, чтобы задать вопрос? – iguanaman