我写了一个使用async/await的多线程应用程序,它旨在按计划时间下载一些内容。为了达到这个目的,它使用'await Task.Delay'。有时每分钟会发送数千个请求。
它按预期工作,但有时我的程序需要记录一些大量的东西。当它这样做时,它会序列化许多对象并将它们保存到文件中。在此期间,我注意到我的预定任务执行得太晚了。我将所有日志记录放在了一个具有最低优先级的单独线程中,这个问题就不那么频繁地发生了,但仍然会发生。问题是,我想知道何时发生了错误,为了知道这一点,我必须使用类似于以下代码:
此外,我发现我也使用的'Task.Run'也会导致延迟。为了监控它,我必须使用更加丑陋的代码:
我必须在每个await和Task.Run之前和之后以及每个异步函数内部使用它,这很丑陋和不方便。我不能将其放入单独的函数中,因为它必须是异步的,我仍然必须等待它。有没有更优雅的解决方案?
编辑:
一些我在评论中提供的信息:
正如@YuvalItzchakov所指出的那样,问题可能是由线程池饥饿引起的。这就是为什么我使用System.Threading.Thread来处理线程池外的日志记录,但正如我所说,问题仍然会偶尔发生。
我有一个四核处理器,并通过从ThreadPool.GetMaxThreads减去ThreadPool.GetAvailableThreads的结果得到0个繁忙的工作线程和1-2个繁忙的完成端口线程。Process.GetCurrentProcess().Threads.Count通常返回约30个。这是一个Windows窗体应用程序,尽管它只有一个带有菜单的托盘图标,但它启动时有11个线程。当它开始每分钟发送数千个请求时,它很快就会上升到30个。
正如@Noseratio建议的那样,我尝试使用ThreadPool.SetMinThreads和ThreadPool.SetMaxThreads进行调整,但它甚至没有改变上述繁忙线程的数量。
它按预期工作,但有时我的程序需要记录一些大量的东西。当它这样做时,它会序列化许多对象并将它们保存到文件中。在此期间,我注意到我的预定任务执行得太晚了。我将所有日志记录放在了一个具有最低优先级的单独线程中,这个问题就不那么频繁地发生了,但仍然会发生。问题是,我想知道何时发生了错误,为了知道这一点,我必须使用类似于以下代码:
var delayTestDate = DateTime.Now;
await Task.Delay(5000);
if((DateTime.Now - delayTestDate).TotalMilliseconds > 6000/*delays up to 1 second are tolerated*/) Console.WriteLine("The task has been delayed!");
此外,我发现我也使用的'Task.Run'也会导致延迟。为了监控它,我必须使用更加丑陋的代码:
var delayTestDate = DateTime.Now;
await Task.Run(() =>
{
if((DateTime.Now - delayTestDate).TotalMilliseconds > 1000/*delays up to 1 second are tolerated*/) Console.WriteLine("The task has been delayed!");
//do some stuff
delayTestDate = DateTime.Now;
});
if((DateTime.Now - delayTestDate).TotalMilliseconds > 1000/*delays up to 1 second are tolerated*/) Console.WriteLine("The task has been delayed!");
我必须在每个await和Task.Run之前和之后以及每个异步函数内部使用它,这很丑陋和不方便。我不能将其放入单独的函数中,因为它必须是异步的,我仍然必须等待它。有没有更优雅的解决方案?
编辑:
一些我在评论中提供的信息:
正如@YuvalItzchakov所指出的那样,问题可能是由线程池饥饿引起的。这就是为什么我使用System.Threading.Thread来处理线程池外的日志记录,但正如我所说,问题仍然会偶尔发生。
我有一个四核处理器,并通过从ThreadPool.GetMaxThreads减去ThreadPool.GetAvailableThreads的结果得到0个繁忙的工作线程和1-2个繁忙的完成端口线程。Process.GetCurrentProcess().Threads.Count通常返回约30个。这是一个Windows窗体应用程序,尽管它只有一个带有菜单的托盘图标,但它启动时有11个线程。当它开始每分钟发送数千个请求时,它很快就会上升到30个。
正如@Noseratio建议的那样,我尝试使用ThreadPool.SetMinThreads和ThreadPool.SetMaxThreads进行调整,但它甚至没有改变上述繁忙线程的数量。