1

At the 2nd iteration, the "file being used" error occurs at the "using (StreamWriter" line. Even though StreamWriter is supposed to auto-close itself after going out of the usings.

EDIT 1: Real Code

Note: mails is a List<MailMessage> (instantiated with From/To addresses)

foreach (var x in mails)
{

                x.Subject = "Updated Google Exchange Rates (" +
                            DateTime.Now.ToString(new CultureInfo("en-US")) +
                            ")";

                StringBuilder emailBody = new StringBuilder();
                emailBody.AppendLine("abc"); //<-- simplified 
                x.Body = emailBody.ToString();

                _txtName = x.Subject.Replace(...); //Replaces invalid file-name chars

                //Note that _txtName will always be unique due to x.Subject's dependency on DateTime
                using (StreamWriter sw = new StreamWriter("./Exchange Rate History/" + _txtName))
                {
                    sw.WriteLine(emailBody);
                    sw.Close();
                }

                Attachment attachment = new Attachment("./Exchange Rate History/" + _txtName);
                attachment.Name = _txtName;
                x.Attachments.Add(attachment);

                SmtpClient smtpClient = new SmtpClient("...")
                {
                    Credentials = new System.Net.NetworkCredential("", ""),
                    Port = 25
                };

                smtpClient.Send(x);
                smtpClient.Dispose();
}

I had to add "sw.Close();" At before the end of the "usings" for this loop to work. Why?

EDIT 2: Oh no! sw.Close() stopped working! "file being used" again.

NoName
  • 9,824
  • 5
  • 32
  • 52
  • 1
    The code you posted looks like it will open a uniquely named file each time (from `y++` incrementing) and is not re-opening the same file. EDIT: Is this your _actual_ code? – Chris Sinclair Apr 22 '14 at 19:39
  • Alright, fine. I'll paste my actual good. Don't blame me if its long. – NoName Apr 22 '14 at 19:40
  • @RedAces: Maybe you should then try to isolate the code to a short, reproducible chunk of code. – Chris Sinclair Apr 22 '14 at 19:41
  • 1
    Funny how if you want REAL answers, REAL code helps to encourage that eh? – David L Apr 22 '14 at 19:41
  • 1
    actually this is a good question but you should post the code that demonstrates the issue.this code would work without any problem – Selman Genç Apr 22 '14 at 19:42
  • 1
    I agree with the above; I copy/pasted the code and ran it without any problem whatsoever (though now I have 200 files polluting my hard drive :P) (EDIT: Note that it works fine writing 200 times to the _same_ single file as well) – Chris Sinclair Apr 22 '14 at 19:45
  • @RedAces: don't be hurry, you can just extrat the part of code where you are getting the exception and add that code in your post. – Sudhakar Tillapudi Apr 22 '14 at 19:47
  • 2
    If this is running on a server responding to a request, is it possible that you have multiple requests executing at the same time or running multiple threads (especially regarding your comment on how the file name is "unique" based on `DateTime.Now`) and so it's not an issue of closing the file, but two independent threads/processes attempting to write to the same file at the same time? The extra close call or simply sampling error is such that it just _happened_ to work when you added `sw.Close()` but run it enough times it will still fail? – Chris Sinclair Apr 22 '14 at 19:52
  • 2
    Not sure if it is the reson of your problems but worth to read http://stackoverflow.com/questions/8477769/why-do-i-need-to-dispose-a-system-net-mail-mailmessage-instance – Steve Apr 22 '14 at 19:54
  • 1
    Regarding your latest edit: `"Oh no! sw.Close() stopped working! "file being used" again."` I'll bet that this is the case, plausibly in combination with Steve's link. I see _no reason_ to assume that each iteration of your `foreach` loop will produce a unique file name. If it iterates fast enough, `DateTime.Now` _may_ produce the _exact same value_. If you have multiple threads running this, or a single thread running fast enough in conjunction with Steve's `Attachment` disposing, it might produce this issue. – Chris Sinclair Apr 22 '14 at 19:57
  • I agree with the comments here. I think threading is probably not an issue but assumption about DateTime.Now uniqueness is failing. Try using a GUID in the file name e.g. Guid.NewGuid().ToString("n") – mtmk Apr 22 '14 at 20:24

1 Answers1

0

Found the problem, and its not StreamWriter not closing itself after usings.

Chris Sinclair is right about DateTime not guaranteeing an unique file name. If your for-loop is short (therefore, fast), you can end up with duplicate names, which is what happened in my case.

For 5 emails, _txtName generated 5 identical file names, meaning I ended up with one file in the end since StreamWriter overwrites by default.

Also, I forgot to use x.Attachments.Dispose(); at the end of each loop. So when it re-iterated, x.Attachments.add() is still trying attach the same file (upload time) while StreamWriter begins to write to the same file cause _txtName generated duplicate names due to DateTime being slower than the for-loop.

TL;DR: The for-loop is too fast too furious.

NoName
  • 9,824
  • 5
  • 32
  • 52