Нужно вручную закрыть StreamWriter в Usings?

На 2-й итерации ошибка «файл используется» возникает в строке «using (StreamWriter»). Несмотря на то, что StreamWriter должен автоматически закрываться после выхода из использования.

ИЗМЕНИТЬ 1. Настоящий код

Примечание: mails - это List<MailMessage> (экземпляр с адресами From / To)

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();
}

Мне пришлось добавить "sw.Close ();" До окончания "использования", чтобы этот цикл работал. Почему?

РЕДАКТИРОВАТЬ 2: О нет! sw.Close () перестала работать! "файл используется" снова.


person NoName    schedule 22.04.2014    source источник
comment
Опубликованный вами код выглядит так, как будто он каждый раз открывает файл с уникальным именем (с увеличением y++) и не открывает повторно один и тот же файл. РЕДАКТИРОВАТЬ: это ваш актуальный код?   -  person Chris Sinclair    schedule 22.04.2014
comment
Хорошо, хорошо. Я вставлю свое собственно хорошее. Не вини меня, если это будет долго.   -  person NoName    schedule 22.04.2014
comment
@RedAces: Может быть, вам тогда стоит попытаться выделить код в короткий воспроизводимый фрагмент кода.   -  person Chris Sinclair    schedule 22.04.2014
comment
Забавно, как если вы хотите НАСТОЯЩИЕ ответы, НАСТОЯЩИЙ код помогает в этом, а?   -  person David L    schedule 22.04.2014
comment
на самом деле это хороший вопрос, но вы должны опубликовать код, демонстрирующий проблему. этот код будет работать без каких-либо проблем   -  person Selman Genç    schedule 22.04.2014
comment
Я согласен с вышеизложенным; Я скопировал / вставил код и запустил его без каких-либо проблем (хотя теперь у меня 200 файлов, загрязняющих мой жесткий диск: P) (РЕДАКТИРОВАТЬ: обратите внимание, что он отлично работает, записывая 200 раз в тот же единственный файл также)   -  person Chris Sinclair    schedule 22.04.2014
comment
@RedAces: не торопитесь, вы можете просто извлечь часть кода, в которой возникает исключение, и добавить этот код в свой пост.   -  person Sudhakar Tillapudi    schedule 22.04.2014
comment
Если это работает на сервере, отвечающем на запрос, возможно ли, что у вас есть несколько запросов, выполняемых одновременно или выполняющих несколько потоков (особенно в отношении вашего комментария о том, как имя файла уникально на основе DateTime.Now), и поэтому это не проблема с закрытием файла, но два независимых потока / процесса пытаются одновременно записать в один и тот же файл? Дополнительный вызов закрытия или просто ошибка выборки такова, что она просто случилась сработала, когда вы добавили sw.Close(), но запустить ее достаточно раз, она все равно не сработает?   -  person Chris Sinclair    schedule 22.04.2014
comment
Не уверен, что это причина ваших проблем, но стоит прочитать stackoverflow.com/questions/8477769/   -  person Steve    schedule 22.04.2014
comment
Относительно вашего последнего редактирования: "Oh no! sw.Close() stopped working! "file being used" again." Держу пари, что это так, вероятно, в сочетании со ссылкой Стива. Я не вижу причин предполагать, что каждая итерация вашего foreach цикла будет давать уникальное имя файла. Если итерация выполняется достаточно быстро, DateTime.Now может выдать точно такое же значение. Если у вас есть несколько потоков, выполняющих это, или один поток работает достаточно быстро в сочетании с Attachment удалением Стива, это может вызвать эту проблему.   -  person Chris Sinclair    schedule 22.04.2014
comment
Я согласен с комментариями здесь. Я думаю, что многопоточность, вероятно, не проблема, а предположение о DateTime. Теперь уникальность не работает. Попробуйте использовать GUID в имени файла, например. Guid.NewGuid (). ToString (n)   -  person ziya    schedule 23.04.2014


Ответы (1)


Обнаружил проблему, и это не StreamWriter, который не закрывается после usings.

Крис Синклер прав в том, что DateTime не гарантирует уникальное имя файла. Если ваш цикл for короткий (следовательно, быстрый), вы можете получить повторяющиеся имена, что и произошло в моем случае.

Для 5 писем _txtName сгенерировал 5 одинаковых имен файлов, то есть в итоге у меня остался один файл, поскольку StreamWriter по умолчанию перезаписывает.

Кроме того, я забыл использовать x.Attachments.Dispose(); в конце каждого цикла. Поэтому, когда он повторяется, x.Attachments.add() все еще пытается прикрепить тот же файл (время загрузки), в то время как StreamWriter начинает запись в тот же файл, потому что _txtName генерирует повторяющиеся имена из-за того, что DateTime работает медленнее, чем цикл for.

TL; DR: цикл for слишком быстрый, слишком яростный.

person NoName    schedule 22.04.2014