简体   繁体   English

尝试以自己的using语句访问MemoryStream时,MemoryStream抛出ObjectDisposedException

[英]MemoryStream throws ObjectDisposedException when trying to access it in its own using statement

I'm trying to use streams to progressively display a jpeg as it loads. 我正在尝试使用流在加载时逐步显示jpeg。 This used to work fine, but this morning I tried running my code and now no images can be loaded because of this error. 这曾经可以正常工作,但是今天早上我尝试运行我的代码,由于这个错误,现在无法加载任何图像。 The relevant code is as follows: 相关代码如下:

using (WebClient wc = new WebClient())
using (Stream streamRemote = wc.OpenRead(url))
using (Stream streamLocal = new MemoryStream((int)fileSize))
{
    int byteSize = 0;
    byte[] buffer = new byte[fileSize];

    while ((byteSize = streamRemote.Read(buffer, 0, buffer.Length)) > 0)
    {
        streamLocal.Write(buffer, 0, byteSize); // Error is here.
        bytesDownloaded += byteSize;

        int progressPercentage = (int)(bytesDownloaded / buffer.Length) * 100;

        if (progressPercentage % 10 == 0)
        {
            imageLoader.ReportProgress(progressPercentage, streamLocal);
        }
    }
}

// Exception thrown: 'System.ObjectDisposedException' in mscorlib.dll
// An exception of type 'System.ObjectDisposedException' occurred in mscorlib.dll but was not handled in user code
// Cannot access a closed Stream.

After using Console.WriteLine at the end of the that final using statement (after the while loop), I've found that the code seems to run through the loop a couple times before throwing that exception. 在最后一个using语句的末尾(在while循环之后)使用Console.WriteLine之后,我发现该代码似乎在抛出该异常之前在循环中运行了两次。

I don't understand why I would be trying to access a closed stream when the code is clearly happening within the using statement that the stream is declared in. I also don't understand why it worked the other day and doesn't now. 我不明白为什么代码声明了该流的using语句中明显发生时为什么要尝试访问封闭的流。我也不明白为什么它在前一天起作用了,但现在不起作用。 Most of the code for this comes from here , so the rest of my method can be found there. 大部分代码都来自这里 ,因此我的方法的其余部分可以在这里找到。 Mine isn't much different apart from some variable name changes and other small changes. 除了一些变量名更改和其他一些小的更改外,我的没有什么不同。 Can anyone help fix this? 谁能帮忙解决此问题?

Edit: My _ProgressChanged event: 编辑:我的_ProgressChanged事件:

private void ImageLoader_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (!fileFailed)
    {
        Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
        new Action(delegate ()
        {
            try
            {
                using (MemoryStream stream = e.UserState as MemoryStream)
                {
                    BitmapImage bmp = new BitmapImage();
                    bmp.BeginInit();
                    using (MemoryStream ms = new MemoryStream(stream.ToArray())) bmp.StreamSource = ms;
                    bmp.EndInit();

                    img_CurrentImage.Source = bmp;
                }
            }
            // A few catch statements here - none of the exceptions here are being thrown anyway so I'll omit the catch statements
        }));
    }
}

As I suspected, it's because you're misusing the MemoryStream in your ProgressChanged handler. 正如我所怀疑的,这是因为您在ProgressChanged处理程序中滥用了MemoryStream

This line: 这行:

using (MemoryStream stream = e.UserState as MemoryStream)

Is taking the stream object that was passed to ProgressChanged() and will later on in the delegate Dispose of it. 正在获取传递给ProgressChanged()的流对象,稍后将在委托中对其进行Dispose But that's exactly the same stream object that you're wondering how it got disposed inside your DoWork method. 但这您想知道如何将其放置在DoWork方法中的流对象相同

That stream doesn't "belong" to the ProgressChanged handler. 该流不“属于” ProgressChanged处理程序。 It shouldn't be disposing of it. 它不应该处理它。

It's somewhat subtle, but in the linked question, the only thing that's done with the passed in stream is to access its ToArray method. 这有些微妙,但是在链接的问题中,传入流唯一要做的就是访问其ToArray方法。 Which you need to also be careful to do since, because ProgressChanged (and Dispatcher.BeginInvoke ) is asynchronous, you could easily be dealing with an already disposed object in this handler (but ToArray is safe to call on disposed MemoryStream s) 您还需要注意这一点,因为ProgressChanged (和Dispatcher.BeginInvoke )是异步的,因此您可以轻松地在此处理程序中处理已经处置的对象(但是ToArray可以安全地调用处置的MemoryStream

You might also consider extracting the byte[] array from the MemoryStream inside your DoWork method and making that the passed state instead of the MemoryStream . 您还可以考虑从DoWork方法内部的MemoryStream提取byte[]数组,并使状态成为通过状态,而不是MemoryStream That would make it far less prone to misuse both now and in any future edits to this code. 这样一来,现在以及以后对该代码进行的任何修改都将更不容易被滥用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 System.ObjectDisposedException 尝试访问 DataContext 时 - System.ObjectDisposedException when trying to access DataContext 尝试使用异步方法访问Thread.CurrentPrincipal时出现ObjectDisposedException - ObjectDisposedException when trying to access Thread.CurrentPrincipal with async method IFormFile 复制到内存流 ObjectDisposedException - IFormFile copy to memorystream ObjectDisposedException 使用IMessageFilter时出现ObjectDisposedException - ObjectDisposedException when using IMessageFilter 尝试上传文件时出现ObjectDisposedException - ObjectDisposedException when trying to upload a file 尝试列出对象时出现System.ObjectDisposedException - System.ObjectDisposedException when trying to list an object 尝试将文件保存到DbContext时抛出ObjectDisposedException - ObjectDisposedException thrown when trying to save files to a DbContext 尝试从SQLiteDataReader读取时遇到ObjectDisposedException - Encountering ObjectDisposedException when trying to read from SQLiteDataReader 一次性:MemoryStream.Capacity在生成PDF文件时引发了System.ObjectDisposedException异常 - Disposable: MemoryStream.Capacity threw an exception of System.ObjectDisposedException when generating PDF file 进行HttpWebRequest时,自定义MSBuild任务将引发ObjectDisposedException - Custom MSBuild Task throws ObjectDisposedException when making a HttpWebRequest
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM