我正在尝试使用流来加载时逐步显示jpeg。这曾经工作正常,但今天早上我尝试运行我的代码,现在没有图像可以加载,因为这个错误。相关代码如下:
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.
在最终使用语句结束后使用Console.WriteLine(在while循环之后),我发现代码似乎在抛出异常之前经过了几次循环。
我不明白为什么当代码明确发生在声明流声明的using语句中时,我会尝试访问一个封闭的流。我也不明白为什么它在前几天工作而现在没有。大多数代码来自here,所以我的方法的其余部分可以在那里找到。除了一些变量名称更改和其他小变化之外,我的差别不大。谁能帮忙解决这个问题?
编辑:我的_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
}));
}
}
我怀疑,这是因为你在你的MemoryStream
处理程序中滥用ProgressChanged
。
这一行:
using (MemoryStream stream = e.UserState as MemoryStream)
正在获取传递给ProgressChanged()
的流对象,稍后将在它的委托Dispose
中。但这是完全相同的流对象,你想知道它是如何在你的DoWork
方法中处理的。
该流不属于ProgressChanged
处理程序。不应该处理它。
它有点微妙,但在链接的问题中,传入流中唯一做的就是访问它的ToArray
方法。你需要谨慎做到这一点,因为ProgressChanged
(和Dispatcher.BeginInvoke
)是异步的,你可以很容易地处理这个处理程序中已经处理好的对象(但ToArray
可以安全地调用处置的MemoryStream
s)
您也可以考虑从byte[]
方法中的MemoryStream
中提取DoWork
数组,并使其成为通过状态而不是MemoryStream
。这将使它现在和将来对此代码的任何编辑都不太容易被滥用。