Reputation: 41
Here is my current code:
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;
}
});
This code does not work correctly, I am looking for a SMALL alternative that does. This code returns some of the arguments in the Message string... What is a good way to multi-threaded string addition? That is what I need.
More info: The Message string will return a, b, and c sometimes while others it will only return just a or b...
I appreciate any help on this, thanks!
Upvotes: 1
Views: 3998
Reputation: 45997
You can use a concurrent collection and make that afterwards to one string
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);
Or try to lock the Item you want to write.
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());
}
}
});
Upvotes: 0
Reputation: 6481
for collect elements AsParallel()
its more appropriate:
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);
Upvotes: 1
Reputation: 10708
Implementing thread safety in this case wuold probably best involve the lock
statement. Remember never to lock on an object you don't have exclusive access to, which in this case cabe method-scoped.
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;
}
});
Upvotes: -1
Reputation: 19702
You could just lock around the Message +=
part:
//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;
}
Upvotes: 1
Reputation: 101701
You can use a thread-safe collection to store the messages such as ConcurrentBag<T>
.Then just make the concetanation after the loop:
var messages = new ConcurrentBag<string>();
Parallel.ForEach(Arguments, Argument =>
{
...
messages.Add(Argument + " => " + response.ReadToEnd());
}
var result = string.Join(Environment.NewLine, messages);
Upvotes: 9