我已通读 TPL 和任务库文档。但是,我仍然不能很清楚地理解下面的案例,现在我需要实现它。
我会简化我的情况。我有一个 IEnumerable<Uri>长度为 1000。我必须使用 HttpClient 为他们提出请求.
我有两个问题。
Parallel.Foreach()吗? ?Task相反,创建大量它们的最佳实践是什么?假设我使用 Task.Factory.StartNew()并将这些任务添加到列表中并等待所有任务。是否有控制最大任务数和最大 HttpClient 的功能(例如 TPL 分区程序)我可以创作吗?SO 上有几个类似的问题,但没有人提到最大值。要求只是使用最大 HttpClient 的最大任务。
提前谢谢你。
最佳答案
i3arnon 对 TPL Dataflow 的回答很好;数据流非常有用,尤其是当您混合使用 CPU 和 I/O 绑定(bind)代码时。我会附和他的观点,即 Parallel 是为 CPU 密集型代码设计的;它不是基于 I/O 代码的最佳解决方案,尤其是不适合异步代码。
如果您想要一个替代解决方案,它可以很好地处理大部分 I/O 代码 - 并且不需要外部库 - 您正在寻找的方法是 Task.WhenAll:
var tasks = uris.Select(uri => SendRequestAsync(uri)).ToArray();
await Task.WhenAll(tasks);
这是最简单的解决方案,但它确实有同时启动所有请求的缺点。特别是如果所有请求都转到同一个服务(或一小组服务),这可能会导致超时。要解决这个问题,您需要使用某种节流...
Is there a feature (such as TPL partitioner) that controls number of maximum tasks and maximum HttpClient I can create?
TPL Dataflow 有很好的 MaxDegreeOfParallelism,一次只能启动这么多。您还可以使用另一个内置函数 SemaphoreSlim 来限制常规异步代码:
private readonly SemaphoreSlim _sem = new SemaphoreSlim(50);
private async Task SendRequestAsync(Uri uri)
{
await _sem.WaitAsync();
try
{
...
}
finally
{
_sem.Release();
}
}
In case of using Task instead, what is the best practice for creating huge number of them? Let's say I use Task.Factory.StartNew() and add those tasks to a list and wait for all of them.
您实际上不想使用 StartNew。它只有一个合适的用例(基于动态任务的并行性),这种情况极为罕见。如果您需要将工作推送到后台线程,现代代码应该使用 Task.Run。但您甚至不需要它作为开始,因此 StartNew 和 Task.Run 都不适合放在此处。
There are couple of similar questions on SO, but no one mentions the maximums. The requirement is just using maximum tasks with maximum HttpClient.
最大值是异步代码真正变得棘手的地方。对于受 CPU 限制(并行)的代码,解决方案很明显:您使用的线程数与内核数一样多。 (好吧,至少你可以开始并根据需要进行调整)。对于异步代码,没有那么明显的解决方案。这取决于很多因素 - 您有多少内存、远程服务器如何响应(速率限制、超时等)等。
这里没有简单的解决方案。您只需测试您的特定应用程序如何处理高并发性,然后限制到较低的数量。
我有一些 slides for a talk试图解释不同技术何时适用(并行、异步、TPL 数据流和 Rx)。如果您更喜欢带有食谱的书面说明,我想您可能会受益于 my book关于并发。
关于c# - IO绑定(bind)操作的并行执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35686341/
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.