我有一个我想同时运行的进程。该进程使用HttpClient
请求并处理json文件。
它开始工作非常快,然后逐渐减慢。我将所有衍生的任务保存到List<Task>
。如果我在执行开始后立即设置了一个断点,那么任务列表中大约有98个任务。在5-10分钟之后,处理进行得非常慢,当我设置断点时,只有大约60个任务在运行,但处理速度非常慢。可能是初始速度的10-20%。
RAM使用情况看起来很好。在开始时,我的CPU运行在90%左右,但是在5-10分钟后它下降到50%,处理的记录数量非常低。
我使用SemaphoreSlim
来控制正在运行的进程数。
static SemaphoreSlim semaphore = new SemaphoreSlim(100, 100);
这就是我产生任务的方式。我正在读取一个非常大的文件(数百万条记录),所以这个while循环需要无限期地运行而不会放慢速度。
List<Task> taskList = new List<Task>();
int currentRow = 0;
using (StreamReader sReader = new StreamReader(processPath + fileName))
{
string dataLine;
while ((dataLine = sReader.ReadLine()) != null)
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
taskList.RemoveAll(x => x.IsCompleted);
semaphore.Wait();
Interlocked.Increment(ref currentRow);
string domain = dataLine.Split(',')[0];
int row = currentRow;
taskList.Add(Task.Run(() => GetArchiveCounts(domain, row, token)));
tokenSource.CancelAfter(TimeSpan.FromSeconds(180));
}
}
Task.WhenAll(taskList).Wait();
我在GetArchiveCounts()
方法中执行IO。我正在传递取消令牌并将其设置为180秒后自动取消,以避免任何线程被永久锁定并导致减速。当我设置断点时,我看不到任何状态为已取消的任务。
我在GetArchiveCounts()
方法中释放信号量:
public static async Task GetArchiveCounts(string domain, int row, CancellationToken token)
{
bool done = false;
while (token.IsCancellationRequested == false && done == false)
{
using (HttpClient client = new HttpClient(httpClientHandler))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(requestUrl, token);
if (response.IsSuccessStatusCode)
{
// omitted code, I just process result here
}
}
done = true;
}
semaphore.Release();
}
我在这里使用的取消模式感觉不对,我猜这可能是我的问题的原因,但我不确定。由于我没有收到任何错误,我很难搞清楚最新情况。我认为应该可以无限期地保持前几百个处理记录的速度,但我无法弄清楚我的代码中应该归咎于什么。
谁能看到我做错了什么?