WinForm高手进,设计器的代码有点疑惑。

abcyzq 2008-10-24 03:26:12
如下系统生成的设计代码,有什么作用?
我注释了1,2,3处代码,只有注释3导致不能关闭窗体。1,2的注释没有影响,窗体可以正常运行。
高手帮忙详细解释哈,或者给个说明此问题的链接文章,谢谢。
namespace WindowsApplication1
{
partial class TestDes
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
1 // private System.ComponentModel.IContainer components = null;

/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
2 // if (disposing && (components != null))
// {
// components.Dispose();

// }

3 // base.Dispose(disposing);
}

#region Windows 窗体设计器生成的代码
...全文
227 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
abcyzq 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 lake_cx 的回复:]
Timer有个隐藏窗体,也就是有个窗体句柄,而串口要打开端口,也就是文件句柄。这些都是Windows内核对象,是操作系统维护的。
[/Quote]

窗体也是非托管资源?
注释掉base.Dispose()方法就不能关闭窗体,说明不能释放资源,推断窗体是非托管资源。
给非托管资源下个准确的定义和范围?
abcyzq 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 paulin 的回复:]
http://www.cnblogs.com/Allnen/archive/2008/05/23/1206081.html
[/Quote]

这篇是好文章!
abcyzq 2008-10-25
  • 打赏
  • 举报
回复
28楼是高手!,结账,谢谢大家了。
lake_cx 2008-10-25
  • 打赏
  • 举报
回复
new操作会分配内存,而这是在.NET语意中定义的,其实它不只分配内存,还会做很多初始化的工作,它会把对象的地址记录起来,并维护一个引用计数。这种对象占用的内存都是托管资源。而对于某些对象,如窗体,除了分配这些成员变量的内存空间外,最终会调用到CreateWindowEx这个API函数,调用到它之后系统会创建一块数据区来存储这个窗体的相关信息,并返回一个句柄(地址经过复杂运算之后的值)来标识这个窗体,因为是API函数分配的内存,自然不在托管平台的管理之下,要释放这个窗体所占的内存要调用DestoryWindow这个API,那么很显然这个窗体的相关信息所占的内存就是非托管资源。因此Form对象既占用的托管资源(成员变量),也占用了非托管资源(窗体句柄)。

所有涉及句柄的对象都类似。

同时,在.NET中也提供了非托管内存的创建,用于与平台交互,如结构体的数据传递等。

从我看来,托管无非是在编译器上做了手脚,将简单的语句编译成复杂的语句,增加了引用计数等操作,同时改写了堆的内存管理器而已。因此可以这么说,使用托管平台下的内存管理器分配的内促就是托管资源,而API函数是基于系统的,它如果有分配内存,那它必然是非托管资源。

再说明一下:你可以这么认为,句柄就是系统内存的一个指针,它指向一个结构体,该结构体是描述某一个内核对象的相关信息,如进程、线程、窗体等。
abcyzq 2008-10-24
  • 打赏
  • 举报
回复
23楼的说的好高深,听起来是这么回事,就是有点难以理解哦。
abcyzq 2008-10-24
  • 打赏
  • 举报
回复
23楼的说的好高深,听起来是这么回事,就是有点难以理解哦。
lovehongyun 2008-10-24
  • 打赏
  • 举报
回复
其实你的疑问就是Dispose这个方法

这是个什么方法呢?
他是IDisposable接口中的方法.执行与释放或重置非托管资源相关的应用程序定义的任务

那么他有什么用呢?

实现此方法时,可通过在包容层次结构中传播调用来确保释放所有保持的资源。例如,如果对象 A 分配对象 B,而对象 B 又分配对象 C,那么 A 的 Dispose 实现必须对 B 调用 Dispose,而 B 反过来必须对 C 调用 Dispose。如果一个对象的基类实现 IDisposable,该对象还必须调用其基类的 Dispose 方法。

如果某对象的 Dispose 方法被调用一次以上,则该对象必须忽略第一次调用后的所有调用。如果对象的 Dispose 方法被多次调用,该对象一定不要引发异常。除 Dispose 之外的实例方法在资源已释放时会引发 ObjectDisposedException。

用户可能期望资源类型使用特定的约定来表示已分配状态和已释放状态。流类即是这样一种示例,传统上认为它们要么打开要么关闭。具有此种约定的类的实施者可能选择实现具有自定义名称(如“Close”)的公用方法来调用 Dispose 方法。

因为 Dispose 方法必须显式进行调用,所以,实现 IDisposable 的对象还必须实现一个终结器,以便在未调用 Dispose 时处理释放资源问题。默认情况下,垃圾回收器会在回收一个对象的内存之前自动调用该对象的终结器。然而,在调用 Dispose 方法后,通常不需要垃圾回收器调用已释放对象的终结器。为防止自动终止,Dispose 实现可以调用 GC.SuppressFinalize 方法
paulin 2008-10-24
  • 打赏
  • 举报
回复
http://www.cnblogs.com/Allnen/archive/2008/05/23/1206081.html
paulin 2008-10-24
  • 打赏
  • 举报
回复
就是资源的释放,这里组件自动生成了而已
如果楼主自己写个类,想要释放相应的对象资源
就需要自己继承IDisposable实现

http://www.yesky.com/116/1891616.shtml
cja03 2008-10-24
  • 打赏
  • 举报
回复
写过组件就知道了。
与用户控件不同,我们新建一个用户控件时,自动生成一个构造函数
而新建一个组件时,是这样的:

public partial class Component1 : Component
{
public Component1()
{
InitializeComponent();
}

public Component1(IContainer container)
{
container.Add(this);

InitializeComponent();
}
}


再想想timer,如果不是手写,而是拉过去的话,会发现它不在窗体内,而是在下边,它不包含UI

而我们给当前窗体类添加一个组件,就会加进
/// <summary>
/// 必需的设计器变量。
/// </summary>
1 // private System.ComponentModel.IContainer components = null;

里面


可以看看添加一个组时时,设计器生成的代码:this.component11 = new MyComboBox.Component1(this.components);


所以,components 包含了所有的组件,在窗体释放时,就清空这个components 。
highfly2008 2008-10-24
  • 打赏
  • 举报
回复
学习了
abcyzq 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 lake_cx 的回复:]
Timer有个隐藏窗体,也就是有个窗体句柄,而串口要打开端口,也就是文件句柄。这些都是Windows内核对象,是操作系统维护的。
[/Quote]

有道理,这些都是非托管资源。
lake_cx 2008-10-24
  • 打赏
  • 举报
回复
Timer有个隐藏窗体,也就是有个窗体句柄,而串口要打开端口,也就是文件句柄。这些都是Windows内核对象,是操作系统维护的。
abcyzq 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 lake_cx 的回复:]
我指的系统资源是非托管资源。
[/Quote]

你的意思是timer,serialport这些组件是占用的是非托管资源?还是组件都是占用非托管资源?
abcyzq 2008-10-24
  • 打赏
  • 举报
回复
少写了个字,越来越想知道。晕死打少了个字,对.net是一点不了解。
shangwei97 2008-10-24
  • 打赏
  • 举报
回复
研究中……
abcyzq 2008-10-24
  • 打赏
  • 举报
回复
此问题明白了,但糊涂的地方更多了。。。越来越知道更多.net内幕。
abcyzq 2008-10-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 lake_cx 的回复:]
楼主你可以拖放一个Timer或者SerialPort,然后往下找,可以找到设计器会创建components,并在他们的构造函数中把components传过去。因为Timer要创建隐藏窗体、SerialPort要打开端口,都要占用系统资源。
[/Quote]

在你说6楼话之后,说9楼这话之前,我已经照你要说的做了。看来我悟性不太差。
xupeihuagudulei 2008-10-24
  • 打赏
  • 举报
回复
学习
lake_cx 2008-10-24
  • 打赏
  • 举报
回复
我指的系统资源是非托管资源。
加载更多回复(9)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧