C# 无法访问已释放的对象

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 无法访问已释放的对象相关的知识,希望对你有一定的参考价值。

string uri = "ftp://xxx.xxx.xxx.xxx";
FtpWebRequest fwr = (FtpWebRequest)WebRequest.Create(new Uri(uri));
fwr.UseBinary = true;
fwr.Credentials = new NetworkCredential("username", "password");
fwr.Method = WebRequestMethods.Ftp.ListDirectory;

WebResponse wr = fwr.GetResponse();
Stream stream = wr.GetResponseStream();
//以下3句导致错误, 后面的 stream 读写会导致对象被释放的问题
Stream stream1 = wr.GetResponseStream();
StreamReader sr = new StreamReader(stream1);
textBox1.Text = sr.ReadToEnd();

int count = 1;
byte[] buff = new byte[2048];
Encoding en = Encoding.Default;

while (count != 0)

count = stream.Read(buff, 0, count);
textBox1.Text += en.GetString(buff, 0, count);


会有如下问题:

等大神来解救
如果用 ReadLine()则正常 ReadToEnd()方法应该会关闭流。
那么,StreamReader sr = new StreamReader(stream1);就是对stream的引用?

参考技术A 不要对同一个流get两次。。
如果需要读取两次的话 先读取到memoryStream中再做第二次处理。。追问

但是:
//textBox1.Text = sr.ReadToEnd();
如果把 sr.ReadToEnd() 改为
sr.RradLine() 就不会报错了,,但是读取的东西就错了

追答

ReadToEnd会直接读取到流的末尾 ReadLine不会

还是那句话...对需要重复使用的资源 自行创建缓存


觉得还是给你一段范例代码来的好。。

WebResponse wr = fwr.GetResponse();
Stream stream = wr.GetResponseStream();

//创建缓冲流
MemoryStream ms = new MemoryStream();
int count ;
byte[] buff = new byte[2048];
while ((count = stream.Read(buff, 0, buff.Length)) > 0) 
  ms.Write(buff, 0, count);

ms.Position = 0;

//下面再执行你的操作
//Stream stream1 = wr.GetResponseStream();
//StreamReader sr = new StreamReader(stream1);
StreamReader sr = new StreamReader(ms);
textBox1.Text = sr.ReadToEnd();

//再执行第二次操作
ms.Position = 0;
//int count = 1;
//byte[] buff = new byte[2048];
Encoding en = Encoding.Default;

while (count != 0)

count = stream.Read(buff, 0, count);
textBox1.Text += en.GetString(buff, 0, count);

追问

麻烦了你,能不能把ReadToEnd ReadLine 出现上面的情况详细说一下啊。关于缓存这些我都还没有概念。

追答

首先你先理解一下“流”的概念

流实质上是对数据的一种读取方式 像水流一样 读取和写入操作是只向前不能回退的
GetResponseStream()获取了一个http请求的回复流 实质上是一个网络流 实际的类为
System.Net.ConnectStream

这个流在读取过程中是不支持Seek的 换而言之 你只能对他读取一遍
但是你的对他明显产生了两次操作 一次是使用StreamReader进行读取 一次是直接Read然后用Encoding转码
为了同一个流能够重复的从头到尾读取两次 你需要在内存中先把流的内容保存下来 也就是我MemoryStream的用处了 这就是创建缓存的意思

ReadToEnd和ReadLine只是sr的两个函数而已 一个是一直读取到流的末尾 一个是读取直到遇到第一个换行符("\r\n")就结束 和整个程序结构其实关系不大

本回答被提问者采纳
参考技术B 用两个WebResponse ,wr1、wr2试试追问

还是一样的问题,,看楼下的回答

c# 无法访问已释放的对象

private void 标准件信息导入ToolStripMenuItem_Click(object sender,EventArgs e)

frmStandardInput frmsin = new frmStandardInput();
frmsin.ShowDialog();


未处理System.ObjectDisposedException
HResult=-2146232798
Message=无法访问已释放的对象。
对象名:“frmStandardInput”。
Source=System.Windows.Forms
ObjectName=frmStandardInput

也许是frmStandardInput这个窗体关闭后又执行了ShowDialog()操作,看看frmStandardInput 窗体的load事件是不是有关闭窗体代码 参考技术A 在哪句报错的,截图看一下? 参考技术B 构造函数是不是有问题?

以上是关于C# 无法访问已释放的对象的主要内容,如果未能解决你的问题,请参考以下文章

C#无法访问已释放的对象

c# topmost模式窗口关闭后,有“无法访问已释放的对象”错误

c# winform 无法访问已释放的对象。 对象名:“System.ServiceModel.Channels.ServiceChannel”。

无法访问已释放的对象,该怎么解决

C#Winform打印预览无法访问已释放的对象。

无法访问已释放的对象。\r\n对象名称: 'ApplicationUserManager'