Cannot access a closed stream
Cannot access a closed stream
Answered by:
Question
I’m using .net 3.5 (can’t use 4.x in this case) and the System.IO.Compression library. I’m using it to compress an Excel file into a ZIP file. Things have been going well until yesterday, when the Excel file crossed some sort of size boundary. Since then I’m getting this exception:
The code I use is:
Has anyone seen this? Is this a bug in my code or something else?
Answers
- Marked as answer by G Britton Wednesday, July 27, 2016 1:37 PM
All replies
The issue is with your part.GetStream call. You are getting a stream that is being managed by the Part. The part is managed by the package. When the package is disposed it flushes all streams and then closes them. Because you’ve already closed the stream the flush call fails. This lines up with the call stack where the exception is occurring when flushing the stream that was called when the package was disposed.
Michael Taylor
http://www.michaeltaylorp3.net
That’s what you’d think. As I understand it (probably wrong!) the stream won’t be closed until all the data is written and the inner double-using statements finish. However, when the using statements finish, that is when the stream would closed, right? And that happens before the package is disposed, I think. At least, that’s my intention!
So what I expect is:
in the inner using, the part.GetStream is read and copied to the output buffer. When there’s no more data to read, the inner using finishes and disposes the dest stream for the output. At that moment, the part.GetStream is still open.
After the inner using finishes, the middle using for «part» finishes and disposes.
Finally, the outer using finishes and disposes the Package, but at that point both inner usings should be finished and disposed.
Is that correct? Or, is stacking the usings 3 levels deep causing the issue?
If not, how would you reorganize my code to cure the problem?
For testing I inserted
at the end of the while loop in the CopyStream method. The message never appeared (though it does for smaller files). So that would seem to say that the while loop never finished. So how could the streams have ever been disposed?
Some more info. Since I thought I understood what you meant, I changed the inner using like this:
in an attempt to not prematurely dispose of the destination stream. However this led to another, different error:
«Finally, the outer using finishes and disposes the Package, but at that point both inner usings should be finished and disposed.»
That is correct, but to clarify. The innermost using is disposing of the part’s stream. If you tried to use the part stream again then you’d get an exception. The middle using statement doesn’t have anything to do with the part or package. It is disposing the source stream that you just copied. The outermost using is cleaning up the package.
Here’s the general flow of what is causing the exception based upon the call stack and what that method does.
Package.Dispose is called but since you used Package.Open it actually is ZipPackage.Dispose
Call ZipArchive.Dispose
If the archive was open for writing then save the file
For each zip block
Update the references
Close the related stream
Flush changes
All this is fine, but what isn’t obvious is that PackagePart, while it doesn’t implement IDisposable, does follow the disposable pattern. Specifically it has a Close method that, when called, disposes of the underlying stream. When you dispose of the package it ultimately will call this close routine. It also flushes the part streams first.
Now, why did this work before and doesn’t now? I would wager that the GC kicked in because of memory constraints. When the GC runs it will auto dispose any objects that aren’t referenced. Unfortunately it is hard to tell which object might be it. Ultimately the issue appears to be the stream associated with the part as that is where the exception is occurring but it is hard to tell. Your code is working with generic Package/PackagePart/Stream objects but internally there are a lot of more concrete types being used so tracing the code is difficult.
Nevertheless I think you might be able to test this hypothesis by forcing a GC after the method executes. This would emulate what happens in a low memory situation. But I don’t know that it would convey any additional information if it actually failed or not. There really isn’t anything in your code that should get pre-maturely disposed outside of your explicit using statements.
Почему я получаю здесь «Cannot access a closed Stream»?
Стек trace выглядит так
[ObjectDisposedException: не удается получить доступ к закрытому потоку.]
System.IO.__Error.StreamIsClosed() +53
Система.IO.MemoryStream.Read (буфер Byte[], смещение Int32, счетчик Int32) +11411219 System.Web.Mvc.FileStreamResult.WriteFile(HttpResponseBase ответ) + 81 System.Web.Mvc.FileResult.ExecuteResult(ControllerContext context) +168
System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
Я читал MemoryStream-не могу получить доступ к закрытому потоку , но это не тот же сценарий, потому что я не использую StreamReader
Edit: все еще не работает с
2 Ответа
Поток был закрыт, как только вы вышли из метода действия, а точнее, из блока using ( var ms = new MemoryStream() ) < .
Вам не нужно избавляться от MemoryStream. Объект FileStreamResult, возвращенный File(ms, «application/pdf», «Test.pdf»); , избавится от него после рендеринга . Код, который фактически отправляет потоковые данные, является :
Вы можете заменить это использование блока на :
чтобы гарантировать, что поток будет удален, если произойдет ошибка.
UPDATE
Как уже упоминал Игорь, и как показывает исходный код, FileStreamResult не сбросит позицию потока. Вам нужно будет установить его на 0 перед вызовом return File(. )
Класс PdfWriter может закрывать ваш поток. Убедитесь, что свойству CloseStream присвоено значение false.
Далее вы не должны использовать using на MemoryStream здесь, так как результат действия FileStreamResult позаботится об удалении потока после его отправки. Прямо сейчас поток фактически закрыт (по dispose) до того, как произойдет отправка.
Кроме того, вы должны искать поток обратно в позицию 0 перед отправкой файла.
Вы можете обернуть всю часть в try. catch , однако, чтобы утилизировать поток в случае ошибки (но GC в конечном итоге позаботится о нем и MemoryStream , если Сули управляется, так что это не обязательно).
Похожие вопросы:
Я столкнулся с загадочной проблемой с удаленным объектом, когда я закрыл свое приложение WPF. Если вы заметили какие-либо ошибки в моей логике, пожалуйста, укажите на них. У меня есть класс.
У меня возникли проблемы с созданием PDF, используя простой пример, найденный здесь . Это мой первый раз, когда я пытаюсь использовать его, и я попробовал несколько вещей и много поисков, но не.
У меня есть рабочий код, использующий библиотеку spring-ws для ответа на запросы soap. Я переместил этот код в другой проект (я объединяю проекты), и теперь он терпит неудачу. Я хотел бы выяснить.
Я получаю Cannot access a closed Stream, когда пытаюсь сохранить книгу ClosedXML (XLWorkbook) в поток памяти. public byte[] GetStream() < using (var stream = new MemoryStream()) <.
Я хочу иметь возможность извлечь значение из json, которое у меня есть,и поместить его в другой файл, а затем и другие значения. Это мой код: somefile = File.open(employee_info.txt, w).
У меня есть несколько различных методов, которые подключаются к удаленному хосту, отправляют сообщение, получают ответ и используют информацию. это прекрасно работало до тех пор, пока я не.
Я пытаюсь создать zipfile в методе MVC, используя компоненты DotNetZip. Вот мой код: public FileResult DownloadImagefilesAsZip() < using (var memoryStream = new MemoryStream()) < using (var zip =.
Это ошибка, которую я получаю при запуске сценария. repo nikhil$ ruby repobuilder.rb Resuming from package:20 Now Processing 21 repobuilder.rb:16:in `gets’: closed stream (IOError) from.
Производственная среда: сервер 2008 R2, пул приложений, работающий как сетевая служба. Я сталкиваюсь с этой проблемой в производстве на определенной линии, и я не могу понять, почему она терпит.
Я попытался использовать ответ отсюда , но это не сработало. У меня есть следующий код: public ActionResult ShowImage() < using (FileStream stream = new.
Cannot access a closed stream
Привет, почему using (var sw = new StreamWriter(ms)) возвращает Cannot access a closed Stream exception . Memory Stream находится над этим кодом.
Какой лучший способ это исправить? Спасибо
6 ответов
Это потому, что StreamReader автоматически закрывает основной поток при его удалении. Оператор using делает это автоматически.
Однако StreamWriter , который вы используете, все еще пытается работать в потоке (также using оператор для писателя теперь пытается избавиться от StreamWriter , который затем пытается закрыть поток).
Лучший способ исправить это: не использовать using и не избавляться от StreamReader и StreamWriter . Смотрите этот вопрос .
Если вы плохо себя чувствуете по поводу sw и sr будучи собранным мусором без утилизации в вашем коде (как рекомендуется), вы можете сделать что-то вроде этого:
Начиная с .net45 вы можете использовать аргумент конструктора LeaveOpen для StreamWriter и все еще используйте оператор using .
Когда использование () для вашего StreamReader заканчивается, он удаляет объект и закрывает поток, который ваш StreamWriter все еще пытается использовать.
Проблема в этом блоке:
Когда StreamReader закрывается (после выхода из использования), он также закрывает свой основной поток, так что теперь MemoryStream закрыто. Когда StreamWriter закрывается, он пытается сбросить все в MemoryStream , но он закрыт.
Не стоит помещать StreamReader в блок использования.
В моем случае (по общему мнению, очень загадочно и вряд ли будет часто воспроизводиться) это вызывало проблему (этот код связан с генерацией PDF с использованием iTextSharp):
Объявление 3-клеточной /колонной таблицы, а затем установка только двух значений для ширины, по-видимому, и вызвало проблему. После того, как я изменил «PdfPTable (3)» на «PdfPTable (2)», проблема пошла по пути конвекционной печи.
когда он выходит из оператора using, автоматически вызывается метод Dispose , закрывающий поток
Hi why using (var sw = new StreamWriter(ms)) returns Cannot access a closed Stream exception . Memory Stream is on top of this code.
What the best way to fix it ? Thanks
6 Answers 6
This is because the StreamReader closes the underlying stream automatically when being disposed of. The using statement does this automatically.
However, the StreamWriter you’re using is still trying to work on the stream (also, the using statement for the writer is now trying to dispose of the StreamWriter , which is then trying to close the stream).
The best way to fix this is: don’t use using and don’t dispose of the StreamReader and StreamWriter . See this question.
If you feel bad about sw and sr being garbage-collected without being disposed of in your code (as recommended), you could do something like that:
Posted by: admin December 21, 2017 Leave a comment
Hi why using (var sw = new StreamWriter(ms)) returns Cannot access a closed Stream exception . Memory Stream is on top of this code.
What the best way to fix it ?
Thanks
This is because the StreamReader closes the underlying stream automatically when being disposed of. The using statement does this automatically.
However, the StreamWriter you’re using is still trying to work on the stream (also, the using statement for the writer is now trying to dispose of the StreamWriter , which is then trying to close the stream).
The best way to fix this is: don’t use using and don’t dispose of the StreamReader and StreamWriter . See this question.
If you feel bad about sw and sr being garbage-collected without being disposed of in your code (as recommended), you could do something like that:
When the using() for your StreamReader is ending, it’s disposing the object and closing the stream, which your StreamWriter is still trying to use.
In my case (admittedly very arcane and not likely to be reproduced often), this was causing the problem (this code is related to PDF generation using iTextSharp):
The declaration of a 3-celled/columned table, and then setting only two vals for the width was what caused the problem, apparently. Once I changed “PdfPTable(3)” to “PdfPTable(2)” the problem went the way of the convection oven.
The problem is this block:
When the StreamReader is closed (after leaving the using), it closes it’s underlying stream as well, so now the MemoryStream is closed. When the StreamWriter gets closed, it tries to flush everything to the MemoryStream , but it is closed.
You should consider not putting the StreamReader in a using block.
when it gets out from the using statement the Dispose method will be called automatically closing the stream
«Cannot access a closed Stream» when using DimeAttachment — ASP.NET Web Services
Hi all.. I’m trying to work with DimeAttachment. Please, take a look at code here — it’s very simple to understand. Server Side: public class MyDimeService : System.Web.Services.WebService < [WebMethod] public void DoNothing() < >> Client Side: public class ClientClass < private void CallServer() < MyDimeService svc = new MyDimeService(); DimeAttachment dimeAttach = new DimeAttachment("image/gif", TypeFormatEnum.MediaType, new MemoryStream()); dimeAttach.Stream = new MemoryStream(); dimeAttach.Stream.Write(new Byte[10], 0, 10); svc.RequestSoapContext.Attachments.Add(dimeAttach) ; svc.DoNothing(); dimeAttach.Stream.Write(new Byte[10], 0, 10); >> What I get, when executing the last command in CallServer() function is: An unhandled exception of type ‘System.ObjectDisposedException’ occurred in mscorlib.dll Additional information: Cannot .
Thread Tools
Display
- Linear Mode
- Switch to Hybrid Mode
- Switch to Threaded Mode
«Cannot access a closed Stream» when using DimeAttachment
I’m trying to work with DimeAttachment.
Please, take a look at code here — it’s very simple to understand.
Server Side:
public class MyDimeService : System.Web.Services.WebService
<
[WebMethod]
public void DoNothing() < >
>
Client Side:
public class ClientClass
<
private void CallServer()
<
MyDimeService svc = new MyDimeService();
DimeAttachment dimeAttach = new DimeAttachment(«image/gif»,
TypeFormatEnum.MediaType, new MemoryStream());
dimeAttach.Stream = new MemoryStream();
dimeAttach.Stream.Write(new Byte[10], 0, 10);
dimeAttach.Stream.Write(new Byte[10], 0, 10);
>
>
What I get, when executing the last command in CallServer() function
is:
An unhandled exception of type ‘System.ObjectDisposedException’
occurred in mscorlib.dll
Additional information: Cannot access a closed Stream.
Why do we want to do it this way ?
This is a simplified code, just to show the problem, but in general
what we want is -> pass a big file in chunks from one side to another
(from client to server).
We can, ofcource, for every chunk, create a new stream and write data
of next chunk to it, but in this case we get much much memory usage.
We have to activate garbage collector to free memory, but, this is not
the best way to do things.
There are 2 questions:
1 —> any idea, why do I get this exception ?
2 —> any idea how to solve the general problem ?
Re: «Cannot access a closed Stream» when using DimeAttachment
We struggled with this one for quite some time. Basically the stream gets
closed automatically (apparently by design). The two things you need to
do are:
a) create a class that inherits from MemoryStream, override the Close()
method and inside it simply set the Position to 0 (nothing more). Use
this class instead of the IO.MemoryStream class.
b) This is only required if you call your server-side from server-side.
Set the position to zero once you’ve read the information out.
ie
Client Side
===========
Public Class MemoryStreamHack
Inherits IO.MemoryStream
Public Overrides Sub Close()
Me.Position = 0
End Sub
End Class
Public Sub Foo()
‘a mem stream to put the data into
Dim MemStream As New MemoryStreamHack
‘the doc to xml
Dim Doc As New System.Xml.XmlTextWriter (MemStream,
System.Text.Encoding.Unicode)
End Sub
Server Side
===========
For Each Attachment As Dime.DimeAttachment In
HttpSoapContext.RequestContext.Attachments
‘P each example
If TypeOf Attachment.Stream Is IO.MemoryStream Then
Info = PInfoXML(CType(Attachment.Stream, IO.MemoryStream))
Attachment.Stream.Position = 0
Exit For
End If
Next Attachment
Re:
We struggled with this one for quite some time. Basically the stream gets
closed automatically (apparently by design). The two things you need to
do are:
a) create a class that inherits from MemoryStream, override the Close()
method and inside it simply set the Position to 0 (nothing more). Use
this class instead of the IO.MemoryStream class.
b) This is only required if you call your server-side from server-side.
Set the position to zero once you’ve read the information out.
ie
Client Side
===========
Public Class MemoryStreamHack
Inherits IO.MemoryStream
Public Overrides Sub Close()
Me.Position = 0
End Sub
End Class
Public Sub Foo()
‘a mem stream to put the data into
Dim MemStream As New MemoryStreamHack
‘the doc to xml
Dim Doc As New System.Xml.XmlTextWriter (MemStream,
System.Text.Encoding.Unicode)
End Sub
Server Side
===========
For Each Attachment As Dime.DimeAttachment In
HttpSoapContext.RequestContext.Attachments
‘P each example
If TypeOf Attachment.Stream Is IO.MemoryStream Then
Info = PInfoXML(CType(Attachment.Stream, IO.MemoryStream))
Attachment.Stream.Position = 0
Exit For
End If
Next Attachment
Re:
We struggled with this one for quite some time. Basically the stream gets
closed automatically (apparently by design). The two things you need to
do are:
a) create a class that inherits from MemoryStream, override the Close()
method and inside it simply set the Position to 0 (nothing more). Use
this class instead of the IO.MemoryStream class.
b) This is only required if you call your server-side from server-side.
Set the position to zero once you’ve read the information out.
Deploy Drive File Stream
This article is for administrators. To learn how to use Drive File Stream, see the user Help Center.
Deploy Drive File Stream to your organization for a quick and easy way for you and your users to access your Drive files from your computer.
How it works
With Drive File Stream, you stream your Drive files directly from the cloud to your Mac or PC, freeing up disk space and network bandwidth. Because Drive files are stored in the cloud, any changes you or your collaborators make are automatically updated everywhere. You’ll always have the latest version.
You can also make Drive files available for offline access. These cached files sync back to the cloud when you’re online, so the latest version is available on all your devices.
Install or deploy Drive File Stream
- Verify that Drive File Stream will work for your organization. You can use Drive File Stream on these operating systems:
- Windows: Windows 7 and up. Windows Server 2012 and up.
- Mac: El Capitan (10.11) and up. For High Sierra (10.13) or newer, follow these steps.
For the best user experience, we recommend that you upgrade to the latest OS version available for your machine. Also make sure to use a supported browser.
Install Drive File Stream on each user’s computer using one of these options:
Let each user install Drive File Stream on their own machine. For this option, users need administrator rights to their computer.
Download the Drive File Stream .exe file and deploy it in silent mode:
- Download GoogleDriveFSSetup.exe .
Download now
Run the installer in silent mode:
GoogleDriveFSSetup —silent —desktop_shortcut
The desktop_shortcut flag for Drive File Stream is optional. Users can also find Drive File Stream in the Windows Task Bar.
Drive File Stream includes desktop shortcuts to Google Docs, Sheets, and Slides by default. You can turn the Docs editors shortcuts off by adding the
—gsuite_shortcuts=false parameter to the installer.
- Download GoogleDriveFileStream.dmg .
Download now - Run the installer in silent mode:
hdiutil mount GoogleDriveFileStream.dmg; sudo installer -pkg /Volumes/Install Google Drive File Stream/GoogleDriveFileStream.pkg -target «/Volumes/Macintosh HD»; hdiutil unmount /Volumes/Install Google Drive File Stream/ - (Recommended) Delete the Backup and Sync applications.
- (Optional) Delete the Google Drive folder at
Note: Use caution deleting this folder, as it may contain content that has not yet been saved or synced.
Drive File Stream comes packaged with Google Update (Windows) or Google Software Update (Mac) to automatically update Drive File Stream on your users’ computers. You can configure policy settings for these applications if you don’t want Drive File Stream to automatically update.
If you have problems installing Drive File Stream, restart the computer where you’re having trouble and try again.
Tip: As an administrator, you can find information about the Drive File Stream installation in the Admin console. You can verify the version number, last sync date, or the amount of offline data on a device.
Uninstall or reinstall Drive File Stream
After you uninstall Drive File Stream from your computer, you can still open your files on the web at drive.google.com.
Step 1: Sign out and quit Drive File Stream.
- In your task bar, open Drive File Stream .
- Click More and then Sign out.
- Return to Drive File Stream , click More and then Quit.
Step 2: Uninstall Drive File Stream
On a single computer:
Use standard procedures to uninstall the Drive File Stream application. Consult the OS instructions for your computer if you need assistance.
Across your organization:
- On Windows, use the command:
%PROGRAMFILES%GoogleDrive File Stream uninstall.exe —silent —force_stop
The —force_stop argument is required if Drive File Stream is currently running. The —silent argument is optional. It will suppress uninstall dialogs and skip end-user confirmation of the uninstall.
The UninstallString registry key for Drive File Stream, ( ComputerHKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall <6BBAE539-2232-434A-A4E5-9A33560C6283>), points to the uninstall.exe.
On macOS, right-click /Applications/Google Drive File Stream.app in Finder, then Move to Trash.
Step 3: Clear files cached on your computer.
To clear the Drive File Stream cache, delete the user folder found here:
On macOS, the library folder may be hidden. To find it:
- Open Finder.
- On your keyboard, hold Option.
- In the menus at the top of your screen, click Go Library.
Warning: Be cautious about clearing the Drive File Stream cache to try to fix general problems. Files are moved here before they’re uploaded. If you clear the cache before an upload is complete, that file will be lost.
- Uninstall Drive File Stream, as described above. Make sure to complete step 3, to clear cached files.
- Redeploy or reinstall Drive File Stream.
Train your users
To notify your users about Drive File Stream and help them get started, you can customize our sample email templates. Pick a template based on whether your users are:
- New to Google Drive
- Transitioning to Drive File Stream from Backup and Sync
To introduce Drive to new users, see the sample Google Drive email for users.
Delete the red comments and modify the email as appropriate for your organization.
SUBJECT: Google Drive just got easier for you and your team
We’re pleased to announce Drive File Stream, a new application for your Mac or PC. Use Drive File Stream to access all your Google Drive files from your computer while using less disk space and decreasing sync time.
How does it work?
With Drive File Stream, you can:
- Quickly see Drive files in Finder/Explorer.
- Browse and organize Drive files without downloading all of them to your computer.
- Choose which files or folders you’d like to make available offline.
- Open files in common apps like Microsoft Office and Adobe Photoshop.
How do I get started?
Visit the Drive Help Center to install Drive File Stream and get started.
Delete “install Drive File Stream” if you’ll deploy this yourself.
—
Known issues
You can’t currently duplicate Google Docs, Sheets, and Slides.
Some virus detection and security software can interfere with the operation of Drive File Stream. If you experience issues, try disabling this software for Drive File Stream and the content cache.