如何使用并行 foreach 毫无问题地添加字符串
本文关键字:添加 字符串 无问题 何使用 并行 foreach | 更新日期: 2023-09-27 18:33:48
这是我当前的代码:
Parallel.ForEach(Arguments, Argument =>
{
if (Argument != Command_Name)
{
WebRequest web_request = WebRequest.Create("https://www.aol.com/?command=1&domain=" + Argument);
web_request.Timeout = 5000;
((HttpWebRequest)web_request).UserAgent = "Mozilla Firefox 5.0";
HttpWebResponse web_response = (HttpWebResponse)web_request.GetResponse();
StreamReader response = new StreamReader(web_response.GetResponseStream(), Encoding.UTF8);
Message += Argument + " => " + response.ReadToEnd() + Environment.NewLine;
}
});
此代码无法正常工作,我正在寻找一个可以正常工作的小替代方案。此代码返回消息字符串中的一些参数...添加多线程字符串的好方法是什么?这就是我所需要的。
更多信息:消息字符串有时会返回 a、b 和 c,而其他字符串只会返回 a 或 b...
我感谢这方面的任何帮助,谢谢!
您可以使用线程安全集合来存储消息,例如 ConcurrentBag<T>
。然后只需在循环后做出承认:
var messages = new ConcurrentBag<string>();
Parallel.ForEach(Arguments, Argument =>
{
...
messages.Add(Argument + " => " + response.ReadToEnd());
}
var result = string.Join(Environment.NewLine, messages);
您可以
锁定Message +=
部分:
//scoped to the same scope as the Message object
private Object thisLock = new Object();
var textResult = response.ReadToEnd() + Environment.NewLine;
lock(thisLock)
{
Message += Argument + " => " + textResult;
}
用于收集元素AsParallel()
更合适:
var lines = Arguments.AsParallel().Select(Argument =>
{
if (Argument == Command_Name) return null;
WebRequest web_request = WebRequest.Create("https://www.aol.com/?command=1&domain=" + Argument);
web_request.Timeout = 5000;
((HttpWebRequest)web_request).UserAgent = "Mozilla Firefox 5.0";
HttpWebResponse web_response = (HttpWebResponse)web_request.GetResponse();
StreamReader response = new StreamReader(web_response.GetResponseStream(), Encoding.UTF8);
return Argument + " => " + response.ReadToEnd();
}).ToArray();
var concate = string.Join(Environment.NewLine, lines);
您可以使用并发集合,然后将其转换为一个字符串
var ThreadSafeList = new System.Collections.Concurrent.ConcurrentBag<string>();
Parallel.ForEach(Arguments, Argument =>
{
if (Argument != Command_Name)
{
WebRequest web_request = WebRequest.Create("https://www.aol.com/?command=1&domain=" + Argument);
web_request.Timeout = 5000;
((HttpWebRequest)web_request).UserAgent = "Mozilla Firefox 5.0";
HttpWebResponse web_response = (HttpWebResponse)web_request.GetResponse();
StreamReader response = new StreamReader(web_response.GetResponseStream(), Encoding.UTF8);
ThreadSafeList.Add(Argument + " => " + response.ReadToEnd());
}
});
string Result = string.Join("", ThreadSafeList);
或者尝试锁定要写入的项目。
StringBuilder Message = new StringBuilder();
Parallel.ForEach(Arguments, Argument =>
{
if (Argument != Command_Name)
{
WebRequest web_request = WebRequest.Create("https://www.aol.com/?command=1&domain=" + Argument);
web_request.Timeout = 5000;
((HttpWebRequest)web_request).UserAgent = "Mozilla Firefox 5.0";
HttpWebResponse web_response = (HttpWebResponse)web_request.GetResponse();
StreamReader response = new StreamReader(web_response.GetResponseStream(), Encoding.UTF8);
lock(Message) //locking here
{
Message.AppendLine(Argument + " => " + response.ReadToEnd());
}
}
});
<</div>
div class="answers"> 在这种情况下,实现线程安全 wuold 可能最好涉及 lock
语句。请记住,永远不要锁定您没有独占访问权限的对象,在本例中为 cabe 方法范围。
object key = new object(); // Empty object serves lightest for locks
Parallel.ForEach(Arguments, Argument =>
{
if (Argument != Command_Name)
{
WebRequest web_request = WebRequest.Create("https://www.aol.com/?command=1&domain=" + Argument);
web_request.Timeout = 5000;
((HttpWebRequest)web_request).UserAgent = "Mozilla Firefox 5.0";
HttpWebResponse web_response = (HttpWebResponse)web_request.GetResponse();
StreamReader response = new StreamReader(web_response.GetResponseStream(), Encoding.UTF8);
lock(key)
Message += Argument + " => " + response.ReadToEnd() + Environment.NewLine;
}
});