Streamwriter, StringBuilder and Parallel loops - multithreading

Sorry for big chunk of code, I couldn't explain that with less.Basically I'm trying to write into a file from many tasks.
Can you guys please tell me what I'm doing wrong? _streamWriter.WriteLine() throws the ArgumentOutOfRangeException.
class Program
{
private static LogBuilder _log = new LogBuilder();
static void Main(string[] args)
{
var acts = new List<Func<string>>();
var rnd = new Random();
for (int i = 0; i < 10000; i++)
{
acts.Add(() =>
{
var delay = rnd.Next(300);
Thread.Sleep(delay);
return "act that that lasted "+delay;
});
}
Parallel.ForEach(acts, act =>
{
_log.Log.AppendLine(act.Invoke());
_log.Write();
});
}
}
public class LogBuilder : IDisposable
{
public StringBuilder Log = new StringBuilder();
private FileStream _fileStream;
private StreamWriter _streamWriter;
public LogBuilder()
{
_fileStream = new FileStream("log.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
_streamWriter = new StreamWriter(_fileStream) { AutoFlush = true };
}
public void Write()
{
lock (Log)
{
if (Log.Length <= 0) return;
_streamWriter.WriteLine(Log.ToString()); //throws here. Although Log.Length is greater than zero
Log.Clear();
}
}
public void Dispose()
{
_streamWriter.Close(); _streamWriter.Dispose(); _fileStream.Close(); fileStream.Dispose();
}
}

This is not a bug in StringBuilder, it's a bug in your code. And the modification you shown in your followup answer (where you replace Log.String with a loop that extracts characters one at a time) doesn't fix it. It won't throw an exception any more, but it won't work properly either.
The problem is that you're using the StringBuilder in two places in your multithreaded code, and one of them does not attempt to lock it, meaning that reading can occur on one thread simultaneously with writing occurring on another. In particular, the problem is this line:
_log.Log.AppendLine(act.Invoke());
You're doing that inside your Parallel.ForEach. You are not making any attempt at synchronization here, even though this will run on multiple threads at once. So you've got two problems:
Multiple calls to AppendLine may be in progress simultaneously on multiple threads
One thread may attempt to be calling Log.ToString at the same time as one or more other threads are calling AppendLine
You'll only get one read at a time because you are using the lock keyword to synchronize those. The problem is that you're not also acquiring the same lock when calling AppendLine.
Your 'fix' isn't really a fix. You've succeeded only in making the problem harder to see. It will now merely go wrong in different and more subtle ways. For example, I'm assuming that your Write method still goes on to call Log.Clear after your for loop completes its final iteration. Well in between completing that final iteration, and making the call to Log.Clear, it's possible that some other thread will have got in another call to AppendLine because there's no synchronization on those calls to AppendLine.
The upshot is that you will sometimes miss stuff. Code will write things into the string builder that then get cleared out without ever being written to the stream writer.
Also, there's a pretty good chance of concurrent AppendLine calls causing problems. If you're lucky they will crash from time to time. (That's good because it makes it clear you have a problem to fix.) If you're unlucky, you'll just get data corruption from time to time - two threads may end up writing into the same place in the StringBuilder resulting either in a mess, or completely lost data.
Again, this is not a bug in StringBuilder. It is not designed to support being used simultaneously from multiple threads. It's your job to make sure that only one thread at a time does anything to any particular instance of StringBuilder. As the documentation for that class says, "Any instance members are not guaranteed to be thread safe."
Obviously you don't want to hold the lock while you call act.Invoke() because that's presumably the very work you want to parallelize. So I'd guess something like this might work better:
string result = act();
lock(_log.Log)
{
_log.Log.AppendLine(result);
}
However, if I left it there, I wouldn't really be helping you, because this looks very wrong to me.
If you ever find yourself locking a field in someone else's object, it's a sign of a design problem in your code. It would probably make more sense to modify the design, so that the LogBuilder.Write method accepts a string. To be honest, I'm not even sure why you're using a StringBuilder here at all, as you seem to use it just as a holding area for a string that you immediately write to a stream writer. What were you hoping the StringBuilder would add here? The following would be simpler and doesn't seem to lose anything (other than the original concurrency bugs):
public class LogBuilder : IDisposable
{
private readonly object _lock = new object();
private FileStream _fileStream;
private StreamWriter _streamWriter;
public LogBuilder()
{
_fileStream = new FileStream("log.txt", FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
_streamWriter = new StreamWriter(_fileStream) { AutoFlush = true };
}
public void Write(string logLine)
{
lock (_lock)
{
_streamWriter.WriteLine(logLine);
}
}
public void Dispose()
{
_streamWriter.Dispose(); fileStream.Dispose();
}
}

I think the cause is because you are accessing the stringBuilder in the Parellel bracket
_log.Log.AppendLine(act.Invoke());
_log.Write();
and inside the LogBuilder you perform lock() to disallow memory allocation on stringBuidler. You are changing the streamwriter to handle the log in every character so would give the parellel process to unlock the memory allocation to stringBuilder.
Segregate the parallel process into distinct action would likely reduce the problem
Parallel.ForEach(acts, act =>
{
_log.Write(act.Invoke());
});
in the LogBuilder class
private readonly object _lock = new object();
public void Write(string logLines)
{
lock (_lock)
{
//_wr.WriteLine(logLines);
Console.WriteLine(logLines);
}
}

An alternate approach is to use TextWriter.Synchronized to wrap StreamWriter.
void Main(string[] args)
{
var rnd = new Random();
var writer = new StreamWriter(#"C:\temp\foo.txt");
var syncedWriter = TextWriter.Synchronized(writer);
var tasks = new List<Func<string>>();
for (int i = 0; i < 1000; i++)
{
int local_i = i; // get a local value, not closure-reference to i
tasks.Add(() =>
{
var delay = rnd.Next(5);
Thread.Sleep(delay);
return local_i.ToString() + " act that that lasted " + delay.ToString();
});
}
Parallel.ForEach(tasks, task =>
{
var value = task();
syncedWriter.WriteLine(value);
});
writer.Dispose();
}
Here are some of the synchronization helper classes
http://referencesource.microsoft.com/#q=Synchronized
System.Collections
static ArrayList Synchronized(ArrayList list)
static IList Synchronized(IList list)
static Hashtable Synchronized(Hashtable table)
static Queue Synchronized(Queue queue)
static SortedList Synchronized(SortedList list)
static Stack Synchronized(Stack stack)
System.Collections.Generic
static IList Synchronized(List list)
System.IO
static Stream Synchronized(Stream stream)
static TextReader Synchronized(TextReader reader)
static TextWriter Synchronized(TextWriter writer)
System.Text.RegularExpressions
static Match Synchronized(Match inner)
static Group Synchronized(Group inner)

It is seems that it isn't problem of Parallelism. It's StringBuilder's problem.
I have replaced:
_streamWriter.WriteLine(Log.ToString());
with:
for (int i = 0; i < Log.Length; i++)
{
_streamWriter.Write(Log[i]);
}
And it worked.
For future reference: http://msdn.microsoft.com/en-us/library/system.text.stringbuilder(v=VS.100).aspx
Memory allocation section.

Related

NUnit OneTimeTearDown Garbage collection best practice

At first, I have declared the variables at the beginning of my class
private AddressRepository sut;
private Mock<TransactionDbContext> mockDBContext;
In the OneTimeSetUp, I have created the set up code
[OneTimeSetUp]
public void Setup()
{
var options = new DbContextOptionsBuilder<TransactionDbContext>().Options;
mockDBContext = new Mock<TransactionDbContext>(options);
var dbSetMock = new Mock<DbSet<Address>>();
var data = ValueTask.FromResult(new Address() { AddressLine1 = "address line 1"
});
dbSetMock.Setup(s => s.FindAsync(It.IsAny<Guid>())).Returns(data);
mockDBContext.Setup(s => s.Set<Address>()).Returns(dbSetMock.Object);
}
Question, do I need to write additional code to handle garbage collection, or should I unassign all variables as following to speeds up GC?
[OneTimeTearDown]
public void TearDown()
{
//unassign all variables
mockDBContext = null;
sut = null;
//Possibly call GC.Collect?
GC.Collect();
}
Any coding advice will be well appreciated.
You should dispose of any disposable external resources, which you acquire. Where you do this depends on where you acquire the resource.
If you acquire it in your test fixture constructor, then let NUnit dispose of it. You do that by having the fixture class implement IDispose.
If you acquire it in a OneTimeSetUp, then dispose of it in the corresponding OneTimeTearDown.
If you acquire it in a SetUp, then dispose of it in the corresponding TearDown.
If you acuire it in a TestMethod, then dispose of it before that method returns. The simplest way to do this is via using.
All that said and explained, your example doesn't seem to acquire any disposable external resources. So I would not do any of those things. :-)
Generally, the time people spend figuring out overly complicated code outweighs any small advantage in efficiency. So wait till you see a performance problem before you fix it.

EntryProcessor without locking entries

In my application, I'm trying to process data in IMap, the scenario is as follows:
application recieves request (REST for example) with set of keys to be processed
application processes entries with given key and returns result - map where key is original key of the entry and result is calculated
for this scenario IMap.executeOnKeys is almost perfect, with one problem - the entry is locked while being processed - and really it hurts thruput. The IMap is populated on startup and never modified.
Is it possible to process entries without locking them? If possible without sending entries to another node and without causing network overhead (sending 1000 tasks to single node in for-loop)
Here is reference implementation to demonstrate what I'm trying to achieve:
public class Main {
public static void main(String[] args) throws Exception {
HazelcastInstance instance = Hazelcast.newHazelcastInstance();
IMap<String, String> map = instance.getMap("the-map");
// populated once on startup, never modified
for (int i = 1; i <= 10; i++) {
map.put("key-" + i, "value-" + i);
}
Set<String> keys = new HashSet<>();
keys.add("key-1"); // every requst may have different key set, they may overlap
System.out.println(" ---- processing ----");
ForkJoinPool pool = new ForkJoinPool();
// to simulate parallel requests on the same entry
pool.execute(() -> map.executeOnKeys(keys, new MyEntryProcessor("first")));
pool.execute(() -> map.executeOnKeys(keys, new MyEntryProcessor("second")));
System.out.println(" ---- pool is waiting ----");
pool.shutdown();
pool.awaitTermination(5, TimeUnit.MINUTES);
System.out.println(" ------ DONE -------");
}
static class MyEntryProcessor implements EntryProcessor<String, String> {
private String name;
MyEntryProcessor(String name) {
this.name = name;
}
#Override
public Object process(Map.Entry<String, String> entry) {
System.out.println(name + " is processing " + entry);
return calculate(entry); // may take some time, doesn't modify entry
}
#Override
public EntryBackupProcessor<String, String> getBackupProcessor() {
return null;
}
}
}
Thanks in advance
In executeOnKeys the entries are not locked. Maybe you mean that the processing happens on partitionThreads, so that there may be no other processing for the particular key? Anyhow, here's the solution:
Your EntryProcessor should implement:
Offloadable interface -> this means that the partition-thread will be used only for reading the value. The calculation will be done in the offloading thread-pool.
ReadOnly interface -> in this case the EP won't hop on the partition-thread again to save the modification you might have done in the entry. Since your EP does not modify entries, this will increase the performance.

While modifying ArrayList with one thread and iterating it with another thread, it is throwing ConcurrentModificationException

I was trying below code.
public class IteratorFailFastTest {
private List<Integer> list = new ArrayList<>();
public IteratorFailFastTest() {
for (int i = 0; i < 10; i++) {
list.add(i);
}
}
public void runUpdateThread() {
Thread thread2 = new Thread(new Runnable() {
public void run() {
for (int i = 10; i < 20; i++) {
list.add(i);
}
}
});
thread2.start();
}
public void runIteratorThread() {
Thread thread1 = new Thread(new Runnable() {
public void run() {
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext()) {
Integer number = iterator.next();
System.out.println(number);
}
}
});
thread1.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
IteratorFailFastTest tester = new IteratorFailFastTest();
tester.runIteratorThread();
tester.runUpdateThread();
}
}
It is throwing ConcurrentModificationException sometimes and at times running successfully.
What I don't understand is, since there are 2 different methods each containing one thread. They will execute one by one. When one thread finishes modifying the list, Thread 2 will start iterating.
I also referred to this link(Why no ConcurrentModificationException when one thread iterating (using Iterator) and other thread modifying same copy of non-thread-safe ArrayList), but it is different scenario.
So, Why is it throwing this exception? Is it because of threads?
Can somebody explain?
You are starting two threads and then doing no further synchronization.
Sometimes, both threads will be running at the same time, and you will get the CME. Other times, the first thread will finish before the second thread actually starts executing. In that scenario won't get a CME.
The reason you get the variation could well be down to things like load on your system. Or it could simply be down to the fact that the thread scheduler is non-deterministic.
Your threads actually do a tiny amount of work, compared to the overheads of creating / starting a thread. So it is not surprising that one of them can return from its run() method very quickly.

Blackberry Thread Image from JSON

I am looking for a way to display images on my ListField from a background thread. First in my drawListRow i try this
path = (String) imagePaths.elementAt(index);
bit = connectServerForImage(path);
g.drawBitmap(xText, y + yText, 80, 200, bit, 0, 0);
but can't scroll smoothly throughout the list, and they say do not do networking or other blocking operations on the UI. But i also try this
private class imgConnection extends Thread
{
public imgConnection() {
super();
}
public void run() {
try {
for (int i = 0; i < imagePaths.size(); i++)
{
final int index = i;
String path = imagePaths.elementAt(index).toString();
bit = connectServerForImage(path);
image.addElement(bit);
}
}
catch (Exception e)
{
System.out.println(e.toString());
}
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
_list.setSize(image.size());
subManager.add(_list);
screen.invalidate();
}
});
}
}
public void drawListRow(ListField list, Graphics g, int index, int y, int w) {
bit = (Bitmap) image.elementAt(index);
g.drawBitmap(xText, y + yText, 80, 200, bit, 0, 0);
}
but nothing happens. Any idea, comments.
You are right, i just started java development 2 weeks ago particularly BB development and i try this link. I want to add a background thread to download image after i got the path url from json return.
first thread:
_connectionthread = new Connection();
_connectionthread.start();
private class Connection extends Thread
{
public Connection()
{
super();
}
public void run() {
try {}
catch (Exception e) {}
}
}
second thread:
_imgConnectionThread = new ImgConnection();
_imgConnectionThread.start();
private class ImgConnection extends Thread
{
public ImgConnection() {
super();
}
public void run() {
try {
}
catch (Exception e)
{
}
}
}
how to update images on ListField?
Answer is based on code from - pastebin.com/90UKTHzP
Terrible code! It's really hard to read and undersand! It looks like you copy pasted several examples from different locations. Also you overriding default behavior with same behavior. Also MainScreen already has VerticalManagerField. Also you're adding list every iteration to manager which will cause IAE. And main one thread is depended on result of second one. They start at the same time, but getting json from server and it's processing could take longer time, so image thread most probably will finish his run without any result.
So main recommendation to fix it - read clean code book! Read more about java development - conventions, multithreading. Read about BB development - UI api, networking.
And finally - start only one thread to get and parse json. After you get it finished - start another thread to get images.
There some minor things that could save you more battery and processor time also - start loading images on demand - when it painted or going to be painted (user scrolls list).
By convention, Java class names start with a capital letter, so imgConnection should really be ImgConnection.
In your sample code, I don't see imgConnection being instantiated anywhere, and I don't see any call to Thread.start(), which is the way a thread i started. Without Thread.start() it is not surprising nothing is happening - the thread is never starting.

How to implement a 'wait' state when using multi-threading in C#

I have a class that I am applying multi-threading to. I would like to only allow 1 thread to 'startSpeaking()' at one time. Here is my attempt:
class VoiceEffect
{
SpeechSynthesizer reader = new SpeechSynthesizer();
static readonly object _locker = new object();
public void createVoiceThread(string str)
{
Thread voicethread = new Thread(() => startSpeaking(str)); // Lambda Process
voicethread.IsBackground = true;
voicethread.Start();
}
public void startSpeaking(string str)
{
lock (_locker)
{
reader.Rate = -2; // Voice effects.
reader.Volume = 100;
reader.Speak(str);
}
}
}
I am also calling createVoiceThread() method from another class. It is called by a similar convention in another class. E.g.
class Program
{
static void Main(string[] args)
{
VoiceEffect ve = new VoiceEffect();
string text = "Hello world, how are you today? I am super-duper!!";
for( int i=0 ; i < 10 ; i++ )
{
ve.createVoiceThread(text);
ve.startSpeaking(text);
Thread.Sleep(1000);
}
}
}
My question is how can I modify this program so that when startSpeaking() is called by any thread, that it only plays a single speech pattern at a time.
I know this question's old as hell, but if I'm understanding your question correctly (that you want all the speech done sequentially, as if it were done on a single thread) you can do something like this:
static class VoiceEffect
{
SpeechSynthesizer reader = new SpeechSynthesizer();
private volatile bool _isCurrentlySpeaking = false;
/// <summary>Event handler. Fired when the SpeechSynthesizer object starts speaking asynchronously.</summary>
private void StartedSpeaking(object sender, SpeakStartedEventArgs e)
{ _isCurrentlySpeaking = true; }
/// <summary>Event handler. Fired when the SpeechSynthesizer object finishes speaking asynchronously.</summary>
private void FinishedSpeaking(object sender, SpeakCompletedEventArgs e)
{ _isCurrentlySpeaking = false; }
private VoiceEffect _instance;
/// <summary>Gets the singleton instance of the VoiceEffect class.</summary>
/// <returns>A unique shared instance of the VoiceEffect class.</returns>
public VoiceEffect GetInstance()
{
if(_instance == null)
{ _instance = new VoiceEffect(); }
return _instance;
}
/// <summary>
/// Constructor. Initializes the class assigning event handlers for the
/// SpeechSynthesizer object.
/// </summary>
private VoiceEffect()
{
reader.SpeakStarted += new EventHandler<SpeakStartedEventArgs>(StartedSpeaking);
reader.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(FinishedSpeaking);
}
/// <summary>Speaks stuff.</summary>
/// <param name="str">The stuff to speak.</param>
public void startSpeaking(string str)
{
reader.Rate = -2; // Voice effects.
reader.Volume = 100;
// if the reader's currently speaking anything,
// don't let any incoming prompts overlap
while(_isCurrentlySpeaking)
{ continue; }
reader.SpeakAsync(str);
}
/// <summary>Creates a new thread to speak stuff into.</summary>
/// <param name="str">The stuff to read.</param>
public void createVoiceThread(string str)
{
Thread voicethread = new Thread(() => startSpeaking(str)); // Lambda Process
voicethread.IsBackground = true;
voicethread.Start();
}
}
This gives you a singleton class that will manage all threads, and all threads will share the _isCurrentlySpeaking variable, which will mean that no speech prompts will ever overlap each other since they'll all have to wait until the variable is cleared before speaking. What I cannot guarantee is the order the prompts will be read (i.e., take control of the message-processing queue), if you submit multiple prompts to the queue while there's a prompt being spoken aloud already. Either way, this should pretty much work.
Your question isn't clear, but you have a single lock variable (_locker) which is static - that means only one thread can ever be executing startSpeaking at a time. It's not clear whether you're trying to make threads wait for each other, or whether your question is because you don't want them to wait for each other.
Either way, having a single static lock used like this is distinctly dubious, IMO. If you can really only effectively have one useful instance of this class, consider making it a singleton. (Generally not nice in terms of design.) If it's fine to have multiple independent instances, then make them independent by making the _locker variable an instance variable.
(I'd also strongly advise you to start following .NET naming conventions.)

Resources