Mar*_*ica 10 powershell multithreading stream dotnet-httpclient
一年前,我编写了一个处理Multipart/form-data请求的cmdlet,并且正在利用.net类HttpClient来实现.我在这里详细描述了它.
简而言之,这是我的cmdlet的核心:
$networkCredential = New-Object -TypeName System.Net.NetworkCredential -ArgumentList @($Credential.UserName, $Credential.Password)
$httpClientHandler = New-Object -TypeName System.Net.Http.HttpClientHandler
$httpClientHandler.Credentials = $networkCredential
$httpClient = New-Object -TypeName System.Net.Http.Httpclient -ArgumentList @($httpClientHandler)
$packageFileStream = New-Object -TypeName System.IO.FileStream -ArgumentList @($packagePath, [System.IO.FileMode]::Open)
$contentDispositionHeaderValue = New-Object -TypeName System.Net.Http.Headers.ContentDispositionHeaderValue -ArgumentList @("form-data")
$contentDispositionHeaderValue.Name = "fileData"
$contentDispositionHeaderValue.FileName = $fileName
$streamContent = New-Object -TypeName System.Net.Http.StreamContent -ArgumentList @($packageFileStream)
$streamContent.Headers.ContentDisposition = $contentDispositionHeaderValue
$streamContent.Headers.ContentType = New-Object -TypeName System.Net.Http.Headers.MediaTypeHeaderValue -ArgumentList @("application/octet-stream")
$content = New-Object -TypeName System.Net.Http.MultipartFormDataContent
$content.Add($streamContent)
try
{
$response = $httpClient.PostAsync("$EndpointUrl/package/upload/$fileName", $content).GetAwaiter().GetResult()
if (!$response.IsSuccessStatusCode)
{
$responseBody = $response.Content.ReadAsStringAsync().GetAwaiter().GetResult()
$errorMessage = "Status code {0}. Reason {1}. Server reported the following message: {2}." -f $response.StatusCode, $response.ReasonPhrase, $responseBody
throw [System.Net.Http.HttpRequestException] $errorMessage
}
return [xml]$response.Content.ReadAsStringAsync().GetAwaiter().GetResult()
}
catch [Exception]
{
throw
}
finally
{
if($null -ne $httpClient)
{
$httpClient.Dispose()
}
if($null -ne $response)
{
$response.Dispose()
}
}
Run Code Online (Sandbox Code Playgroud)
我在VSTS Build任务中使用此代码超过一年成功.最近它开始间歇性地失败了.在一次运行中它成功然后下一次失败,依此类推.我不明白为什么会这样,我会用一些帮助.
PostAsync方法调用时代码失败,以下是我看到的异常:
2017-03-24T15:17:38.4470248Z ##[debug]System.NotSupportedException: The stream does not support concurrent IO read or write operations.
2017-03-24T15:17:38.4626512Z ##[debug] at System.Net.ConnectStream.InternalWrite(Boolean async, Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
2017-03-24T15:17:38.4626512Z ##[debug] at System.Net.ConnectStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
2017-03-24T15:17:38.4626512Z ##[debug] at System.Net.Http.StreamToStreamCopy.TryStartWriteSync(Int32 bytesRead)
2017-03-24T15:17:38.4626512Z ##[debug] at System.Net.Http.StreamToStreamCopy.BufferReadCallback(IAsyncResult ar)
2017-03-24T15:17:38.4626512Z ##[debug]--- End of stack trace from previous location where exception was thrown ---
2017-03-24T15:17:38.4626512Z ##[debug] at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
2017-03-24T15:17:38.4626512Z ##[debug] at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
2017-03-24T15:17:38.4626512Z ##[debug] at CallSite.Target(Closure , CallSite , Object )
2017-03-24T15:17:38.4939015Z ##[error]The stream does not support concurrent IO read or write operations.
Run Code Online (Sandbox Code Playgroud)
我试图在不同的构建服务器,托管代理等上执行此操作,但结果是一样的.此外,如果我尝试从ISE的构建服务器上的交互式会话中执行此代码,我就无法让代码失败.我提出在VSTS类似的问题建立工作项目在这里,但直到现在,没有运气.
有没有人有建议或我可以做的测试,以了解发生了什么,为什么这会失败?
我会很感激任何提示.
更新1:
我通过Start-Job cmdlet将其作为后台作业运行来执行我的代码,我无法让它失败.因此,它需要与VSTS代理执行我的代码的方式相关.我会继续挖掘.如果您有任何建议,他们仍然欢迎.
System.Net.Http.StreamContent并被System.IO.FileStream实例化但未被处置。
添加要调用的代码,Dispose就像在块中所做的那样finally。
try
{
# enclose the program
}
finally
{
if($null -ne $streamContent)
{
$streamContent.Dispose()
}
if($null -ne $packageFileStream)
{
$packageFileStream.Dispose()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
644 次 |
| 最近记录: |