【发布时间】:2015-10-18 06:18:55
【问题描述】:
我正在使用控制台应用程序,我需要读取 20 个 URI 批次,我发现通过执行所有任务并并行运行它们,然后在不同线程中对完成的结果进行排序,可以大大提高速度(允许获取下一批)。
在我目前使用的调用中,每个线程在获取响应流时都会阻塞,我还看到有一个异步版本的相同方法GetResponseAsync。
我了解通过使用异步 Await and Async in same line 而不是阻塞来释放线程池有好处:
异步版本
return Task.Run(async () =>
{
var uri = item.Links.Alternate();
var request = (HttpWebRequest)WebRequest.Create(uri);
var response = await request.GetResponseAsync();
var stream = response.GetResponseStream();
if (stream == null) return null;
var reader = new StreamReader(stream);
return new FetchItemTaskResult(reader.ReadToEnd(), index, uri);
});
屏蔽版
return Task<FetchItemTaskResult>.Factory.StartNew(() =>
{
var uri = item.Links.Alternate();
var request = (HttpWebRequest)WebRequest.Create(uri);
var response = request.GetResponse();
var stream = response.GetResponseStream();
if (stream == null) return null;
var reader = new StreamReader(stream);
return new FetchItemTaskResult(reader.ReadToEnd(), index, uri);
});
但是,我在异步版本的控制台应用程序上看到奇怪的暂停,其中 System.Timers.Timer elapsed 事件停止被调用很多秒(当它应该每秒关闭时)。
阻塞处理器每秒运行大约 3,500 个项目,所有内核的 CPU 使用率约为 30%。
async on 每秒运行大约 3,800 个事件,CPU 使用率略高于阻塞,但并不高(只有 5%)......但是我使用的计时器似乎暂停了大约 10 到 15 秒每分钟左右一次,在我的Main() 函数中:
private static void Main(string[] args)
{
// snip some code that runs the tasks
var timer = new System.Timers.Timer(1000);
timer.Elapsed += (source, e) =>
{
Console.WriteLine(DateTime.UtcNow);
// snip non relevant code
Console.WriteLine("Commands processed: " + commandsProcessed.Sum(s => s.Value) + " (" + logger.CommandsPerSecond() + " per second)");
};
timer.Start();
Console.ReadKey();
}
因此,在使用异步时,计时器和线程池似乎有些相关(并且只有异步,阻塞时没有暂停),或者可能不相关,无论哪种方式,请知道发生了什么以及如何进一步诊断?
【问题讨论】:
-
"snip non-related code" 嗯...那是什么?也许 System.Timers.Timer 不会并行调用回调,不确定。一个回调调用可能会阻止下一个。删除所有代码并测试。
-
可能所有线程池线程都忙于运行该部分直到等待或任务完成后。所以你的线程池可能没有一个未占用的线程来运行你的计时器的经过事件
-
为了体验,尝试将
ThreadPool的大小增加为ThreadPool.SetMinthreads/ThreadPool.SetMaxThreads。有什么改变吗? -
我在想,作为 POC,也许用您自己的后台线程替换计时器,该线程卡在一个循环上休眠 1000 并运行您在经过的回调中运行的任何内容,例如 @987654322 @
-
你会说你的异步块中的代码被调用多少次?
标签: c# multithreading async-await task-parallel-library