Dispose如果没有被调用过,在GC处理它的对象是就会在对象的 Finally 过程中自动调用它。实际上,Dispose并不不需要你去调用。除非你知道手工提前调用Dispose有什么不得已,否则这个方法迟早会被系统自动调用的。
解决方案 »
- 如何读取指纹考勤机数据
- 求正则表达式
- FtpWebRequest 非root用户 DownLoad文件
- 请教一个在winform里上传文件的问题
- 各位大虾帮帮忙啊。急用。跪求]异常信息:System.NullReferenceException: 未将对象引用设置到对象的实例
- 请教:(三楼楼长)的OA问题,我安装以后没有找到配置文件config.inc。是否可以重建这个文件?文件位置?文件内容(特别是server名用户名密码
- 我做的一个 “Note” 有 vs.net 选项卡一样的界面。附全部代码。
- 只有你们才会帮我了 在windows窗体中的 DataGrid 怎样做才可以让他显示出 Excel表格的样式
- C# 遍历对象数据
- 如何得到datagrid某个cell对应的数据对象
- 如何用C#实现在RichTextBox中添加图片水印。。
- c# 如何将16位/通道图转换为8位的
{
try
{
this.Dispose(false);
}
finally
{
base.Finalize();
}
}这样的代码。例如 DbConnection、Process、Thread 之类的,不是控件,但是是组件。而另外一堆类型,例如 FileStream 等等,也定义了跟 Component.Finalize 一样的(调用 Dispose 的)操作。因此通常你根本用不着调用Dispose,提前调用它反而是浪费时间。只有在你说的明白“为什么要提前调用 Dispose ”的时候才应该纠结 Using、Dispose 的问题。
{
if (m.Msg != 0x10)
{
base.WndProc(ref m);
}
else
{
//Dispose();
}
}
运行,你会发现,窗体关不掉了。去掉注释,则可以关掉。这说明Dispose非但不是“无用”,而且相当有用。那么究竟是谁调用了它呢?
在Dispose方法内下一个断点,然后F5调试程序,关闭窗体,我们发现它被调用了,我们可以在调用堆栈中清楚地看到,是wmclose这个方法调用了它。幸好,微软公布了.net的源代码,我们可以看到:http://referencesource.microsoft.com/#System.Windows.Forms/ndp/fx/src/winforms/Managed/System/WinForms/Form.cs#835f7070c7e52263private void WmClose(ref Message m) {
FormClosingEventArgs e = new FormClosingEventArgs(CloseReason, false);
// Pass 1 (WM_CLOSE & WM_QUERYENDSESSION)... Closing
//
if (m.Msg != NativeMethods.WM_ENDSESSION) {
if (Modal) {
if (dialogResult == DialogResult.None) {
dialogResult = DialogResult.Cancel;
}
CalledClosing = false;
// if this comes back false, someone canceled the close. we want
// to call this here so that we can get the cancel event properly,
// and if this is a WM_QUERYENDSESSION, appriopriately set the result
// based on this call.
//
// NOTE: We should also check !Validate(true) below too in the modal case,
// but we cannot, because we didn't to this in Everett (bug), and doing so
// now would introduce a breaking change. User can always validate in the
// FormClosing event if they really need to. :-(
//
e.Cancel = !CheckCloseDialog(true);
}
else {
e.Cancel = !Validate(true);
// Call OnClosing/OnFormClosing on all MDI children
if (IsMdiContainer) {
FormClosingEventArgs fe = new FormClosingEventArgs(CloseReason.MdiFormClosing, e.Cancel);
foreach(Form mdiChild in MdiChildren) {
if (mdiChild.IsHandleCreated) {
mdiChild.OnClosing(fe);
mdiChild.OnFormClosing(fe);
if (fe.Cancel) {
// VSWhidbey 173789: Set the Cancel property for the MDI Container's
// FormClosingEventArgs, as well, so that closing the MDI container
// will be cancelled.
e.Cancel = true;
break;
}
}
}
}
//Always fire OnClosing irrespectively of the validation result
//Pass the validation result into the EventArgs...
// VSWhidbey#278060. Call OnClosing/OnFormClosing on all the forms that current form owns.
Form[] ownedForms = this.OwnedForms;
int ownedFormsCount = Properties.GetInteger(PropOwnedFormsCount);
for (int i = ownedFormsCount-1 ; i >= 0; i--) {
FormClosingEventArgs cfe = new FormClosingEventArgs(CloseReason.FormOwnerClosing, e.Cancel);
if (ownedForms[i] != null) {
//Call OnFormClosing on the child forms.
ownedForms[i].OnFormClosing(cfe);
if (cfe.Cancel) {
// Set the cancel flag for the Owner form
e.Cancel = true;
break;
}
}
}
OnClosing(e);
OnFormClosing(e);
}
if (m.Msg == NativeMethods.WM_QUERYENDSESSION) {
m.Result = (IntPtr)(e.Cancel ? 0 : 1);
}
if (Modal) {
return;
}
}
else {
e.Cancel = m.WParam == IntPtr.Zero;
}
// Pass 2 (WM_CLOSE & WM_ENDSESSION)... Fire closed
// event on all mdi children and ourselves
//
if (m.Msg != NativeMethods.WM_QUERYENDSESSION) {
FormClosedEventArgs fc;
if (!e.Cancel) {
IsClosing = true;
if (IsMdiContainer) {
fc = new FormClosedEventArgs(CloseReason.MdiFormClosing);
foreach(Form mdiChild in MdiChildren) {
if (mdiChild.IsHandleCreated) {
mdiChild.OnClosed(fc);
mdiChild.OnFormClosed(fc);
}
}
}
// VSWhidbey#278060. Call OnClosed/OnFormClosed on all the forms that current form owns.
Form[] ownedForms = this.OwnedForms;
int ownedFormsCount = Properties.GetInteger(PropOwnedFormsCount);
for (int i = ownedFormsCount-1 ; i >= 0; i--) {
fc = new FormClosedEventArgs(CloseReason.FormOwnerClosing);
if (ownedForms[i] != null) {
//Call OnClosed and OnFormClosed on the child forms.
ownedForms[i].OnClosed(fc);
ownedForms[i].OnFormClosed(fc);
}
}
fc = new FormClosedEventArgs(CloseReason);
OnClosed(fc);
OnFormClosed(fc);
Dispose();
}
}
}
看到函数最后一行了么?就是在这里调用的。那么GC会不会自动调用Dispose方法呢?显然不会。我们可以继续一个实验,新建一个控制台程序,然后编写如下代码:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace ConsoleApplication1
{
class Program : IDisposable
{
static void Main(string[] args)
{
Program p = new Program();
} public void Dispose()
{
throw new NotImplementedException();
}
}
}显然,如果Dispose方法被调用,会丢出异常,我们运行这个程序——什么也没有发生。这就说明GC绝对没有这个功能。怎么样让GC的时候触发Dispose呢?我们需要手工写:
~Program()
{
Dispose();
}
C#的析构函数就是Finalize函数。此时再运行,就会调用了。顺便说下,Application.OpenForms集合始终保持着Form窗体的引用,所以除非关闭窗体,否则,GC永远没有可能清理Form对象。
protected override void WndProc(ref System.Windows.Forms.Message m)
{
if (m.Msg != 0x10)
{
base.WndProc(ref m);
}
else
{
//Dispose();
}
}补充一点给楼主:
在用户点击 Close 按钮的时候,会触发 WM_CLOSE (0x0010) 消息,并由 WndProc 进行相应的处理,版主在此地的 demo 就是在 close form 行为触发的时候,略过基类的 WndProc 方法,而在 WndProc 内部会触发对 WmClose 方法的调用,参见版主放出来的源代码链接。所以,当你什么也不做的时候,系统是以 WndProc 为入口对 Dispose 方法调用的。protected override void WndProc(ref Message m) {
switch (m.Msg) {
case NativeMethods.WM_NCACTIVATE:
// ......
case NativeMethods.WM_CLOSE:
if (CloseReason == CloseReason.None) {
CloseReason = CloseReason.TaskManagerClosing;
}
WmClose(ref m);
break;
case NativeMethods.WM_QUERYENDSESSION:
// ......
}
}