Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7547061
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 30, 20262026-05-30T09:21:25+00:00 2026-05-30T09:21:25+00:00

Sorry for big chunk of code, I couldn’t explain that with less.Basically I’m trying

  • 0

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();
    }
}
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-30T09:21:27+00:00Added an answer on May 30, 2026 at 9:21 am

    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:

    1. Multiple calls to AppendLine may be in progress simultaneously on multiple threads
    2. 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();
        }
    }    
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am sorry for pasting a big chunk of code but i really want
Sorry the title isn't more help. I have a database of media-file URLs that
Sorry for the confusing title. Basically I made a BinaryReader class that reads in
I'm trying to pass a variable from my main swf to another one that's
We have a big winforms C# application, that's basically a frontend for some databases
I've a litle big problem with java heap memory I'm trying to migrate from
Hi Sorry for posting a big dump of code but I'm very new at
I'm sorry that I couldn't figure out a way to express the question more
IMPORTANT EDIT: Sorry everyone, i made a big mistake in the structure. char *name;
the question is one of design. i'm gathering a big chunk of performance data

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.