Ooookay,所以這對我來說是一個很好的一周了。
首先,這是針對 Framework 4.8(超出我的控制范圍)。
我制作了一個任務串列,使用Task.Runlambda 來呼叫一個異步函式,該函式呼叫第 3 方 API 并回傳:Task<List<Dictionary<string, object>>>
任務數為 75。
API 有分頁要求,所以呼叫函式需要 start 和 end 引數,基于構建任務串列的回圈的迭代器。
到目前為止,一切都直截了當。
同樣直截了當的是,在Task.WaitAll我得到錯誤的結果之后,因為閉包關閉了變數,而不是值。迭代器在任務分離之前很久就處于最大值,因此絕大多數最終會出現錯誤的分頁。
**** 但是,它們都運行到完成。****
現在,每當我嘗試解決關閉問題時,我都會得到一致的結果,其中只有一些任務運行完成,其余的都失敗了。我努力了:
- 將迭代器分配給 lambda 中的新變數
- 使用
Task.Factory.StartNew和傳遞迭代器作為狀態物件 - 上述的變體,但將開始和結束計算移至呼叫函式
在所有情況下,結果都是一樣的:從少數到三分之一的任務完成,其余的都失敗了,通常是前者。
AggregateException據我所知,該系列幾乎沒有提供任何見解。
一般例外是通常的“發生了一個或多個錯誤”,內部例外暗示 movenext 失敗(?)。堆疊跟蹤是最小的單行。
這里會發生什么?
謝謝您的幫助。
-威廉
呼叫函式
public async Task<List<Dictionary<string, object>>> ExecuteAsyncJSON(
string requestSource = "fields", string searchCount = "", Object iteration = null)
{
string url = requestSource;
// Add possible parameters.
if (searchCount != "" && iteration != null)
{
// divide count by 500 remainder for pagination
int quotient = (Int32.Parse(searchCount) / 500);
int remainder = Int32.Parse(searchCount) % 500;
int i = Convert.ToInt32(iteration);
int add = i == quotient ? remainder : 500;
int start = i * 500;
int end = (i * 500) add;
if (url.Contains("?"))
{
url = url "&start=" start.ToString() "&end=" end.ToString();
}
else
{
url = url "?start=" start.ToString() "&end=" end.ToString();
}
}
try
{
// make the call and get the response
using (HttpResponseMessage response = await someclient.GetAsync(url))
// this calls the API through an HttpClient
{
if (response.IsSuccessStatusCode)
{
var serializer = new JavaScriptSerializer();
var responseBodyAsText = await response.Content.ReadAsStringAsync();
var returnData = new List<Dictionary<string, object>>();
returnData = serializer
.Deserialize<List<Dictionary<string, object>>>(responseBodyAsText);
return returnData;
}
else
{
throw new Exception(response.ReasonPhrase);
}
}
}
catch
{
throw new Exception();
}
}
試圖完成這一切的主要內容
var requestSource = "searches/" searchId "/members";
var searchCount = 37301;
int quotient = (Int32.Parse(searchCount) / 500);
var tasks = new List<Task<List<Dictionary<string, object>>>>();
// Put the task list together.
// Using the StartNew with state object to pass the iterator in.
for (var i = 0; i <= quotient; i )
{
var task = Task.Factory.StartNew((iteration) =>
{
var returnData = ExecuteAsyncJSON(requestSource, searchCount, iteration);
return returnData;
}, i)
.Unwrap();
tasks.Add(task);
}
try
{
Task.WaitAll(tasks.ToArray());
}
catch (AggregateException ae)
{
//throw ae;
}
List<Dictionary<string, object>> completedResults
= new List<Dictionary<string, object>>();
List<Task<List<Dictionary<string, object>>>> faultedResults
= new List<Task<List<Dictionary<string, object>>>>();
foreach (Task<List<Dictionary<string, object>>> listTask in tasks)
{
if (listTask.Status == TaskStatus.RanToCompletion)
completedResults.AddRange(listTask.Result);
if (listTask.Status == TaskStatus.Faulted)
faultedResults.Add(listTask);
}
除錯資料
WaitAll AggregateException 是:
One or more errors occurred
Exception of type 'System.Exception' was thrown.
at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.WaitAll(Task[] tasks, Int32 millisecondsTimeout)
at System.Threading.Tasks.Task.WaitAll(Task[] tasks)
at Smu.Bbec.Emma.API.EmmaAPI.<GetMembersMatchingSearch>d__22.MoveNext() in [reference to Task.WaitAll(tasks.ToArray());]
在 76 次呼叫中,4 次正常完成,然后 72 次失敗并出現完全相同的內部例外:
System.Exception: Exception of type 'System.Exception' was thrown.
at Smu.Bbec.Emma.API.EmmaAPI.<ExecuteAsyncJSON>d__8.MoveNext() in [reference to code that makes the actual call to the API]
我設定了一些斷點,結果如下:
A task was canceled.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at Smu.Bbec.Emma.API.EmmaAPI.<ExecuteAsyncJSON>d__8.MoveNext() in f:\\TestApps\\Smu.Bbec.Emma\\Smu.Bbec.Emma.API\\EmmaAPI.cs:line 100"
沒有內在的例外。
還有這個品種;
An error occurred while sending the request.
Inner exception: The request was aborted: The request was canceled (System.Exception {System.Net.WebException})
這是我在取消時擁有的完整除錯資料(已洗掉敏感資料):
$exception {"A task was canceled."} System.Threading.Tasks.TaskCanceledException
this {**********.EmmaAPI} **********.EmmaAPI
_accountId "********" string
_authorization "MTg4NzblahblahblahblahmM6MDNmYzU1blahblahblahblahjM=" string
_baseUri {https://api.e2ma.net/********/} System.Uri
_baseUrl "https://api.e2ma.net/********/" string
_publicKey "********" string
_secretKey "********" string
emmaClient {System.Net.Http.HttpClient} System.Net.Http.HttpClient
BaseAddress {https://api.e2ma.net/********/} System.Uri
DefaultRequestHeaders {Accept: application/json Authorization: Basic MblahblahblahblahTFjYmblahblahblahblahM4M2IyMjM=} System.Net.Http.Headers.HttpRequestHeaders
MaxResponseContentBufferSize 2147483647 long
Timeout {00:01:40} System.TimeSpan
baseAddress {https://api.e2ma.net/********/} System.Uri
defaultRequestHeaders {Accept: application/json Authorization: Basic MTgblahblahblahblah4Y2blahblahblahblahNmYzblahblahblahblahjM=} System.Net.Http.Headers.HttpRequestHeaders
disposeHandler true bool
disposed (System.Net.Http.HttpMessageInvoker) false bool
disposed false bool
handler {System.Net.Http.HttpClientHandler} System.Net.Http.HttpMessageHandler {System.Net.Http.HttpClientHandler}
maxResponseContentBufferSize 2147483647 long
operationStarted true bool
pendingRequestsCts {System.Threading.CancellationTokenSource} System.Threading.CancellationTokenSource
timeout {00:01:40} System.TimeSpan
Static members
requestSource "searches/17297143/members" string
searchCount "37810" string
iteration 67 object {int}
url "searches/17297143/members?start=33500&end=34000" string
uj5u.com熱心網友回復:
我找到了我的難題的答案。
結果發現與此處發布的問題相同:
c# 在 await 呼叫中取消了一個任務
我的解決方案是將.Timeout = TimeSpan.FromMinutes(30)添加到我的 HttpClient 中。
感謝 Theodor Zoulias、Stephen Cleary 以及所有在這里幫助我的人。
干杯!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513498.html
