加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – System.Timers.Timer在Console App中使用带有异步的Task.R

发布时间:2020-12-15 22:17:29 所属栏目:百科 来源:网络整理
导读:我正在使用一个控制台应用程序,我需要读取20个URI的批次,并且通过完成所有任务并并行运行它们然后在不同的线程中对结果进行排序(允许下一个),我发现了大量的速度提升要获取的批次). 在我当前使用的调用中,每个线程在获得响应流时都会阻塞,我也看到有相同方法
我正在使用一个控制台应用程序,我需要读取20个URI的批次,并且通过完成所有任务并并行运行它们然后在不同的线程中对结果进行排序(允许下一个),我发现了大量的速度提升要获取的批次).

在我当前使用的调用中,每个线程在获得响应流时都会阻塞,我也看到有相同方法GetResponseAsync的异步版本.

我知道通过使用async 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(),uri);
});

但是我在控制台应用程序上看到了异常版本的奇怪暂停,其中System.Timers.Timer已经过去的事件停止被调用了很多秒(当它应该每秒关闭时).

阻塞的每秒运行大约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();
}

所以看起来计时器和线程池是一些在使用异步时的相关性(并且只有异步,阻塞时没有暂停),或者可能没有,无论是任何想法,请问是什么以及如何进一步诊断?

解决方法

the timer and thread pool are some how related

你的怀疑是正确的.发生的事情基本上被称为臭名昭着的线程饥饿,即所有线程都忙,因此ThreadPool没有足够的线程来运行事件委托.

一旦在ASP.NET中运行,autoConfig="True"确保您获得足够的线程(在峰值的情况下并非总是如此),并确保您不受连接限制的约束.但是在控制台应用程序中,您必须自己完成.

所以只需添加此片段,我敢打赌你的问题就会消失:

ThreadPool.SetMinThreads(100,100);
ServicePointManager.DefaultConnectionLimit = 1000;

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读