首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

关于“无法访问已释放的对象”,老有关问题,不知道怎么解决

2012-09-13 
关于“无法访问已释放的对象”,老问题,不知道如何解决最近做程序,采用定时器加委托方式对进行控制程序如下:C

关于“无法访问已释放的对象”,老问题,不知道如何解决
最近做程序,采用定时器加委托方式对进行控制程序如下:



C# code
        System.DateTime oldtime=new DateTime();        delegate void SetTextCallback(string strTime);//定义托管函数        System.Timers.Timer t = new System.Timers.Timer(100);//实例化Timer类         bool closeFlag;        public Form1()        {            InitializeComponent();        }private void timeClass_Click(object sender, EventArgs e){    t.Elapsed+= new System.Timers.ElapsedEventHandler(theout);//到达时间的时候执行事件;     t.AutoReset = true;//设置是执行一次(false)还是一直执行(true);     t.Enabled = true;//是否执行System.Timers.Timer.Elapsed事件;    }public void theout(object source, System.Timers.ElapsedEventArgs e) //定时器调用{    System.DateTime currentTime = new DateTime();    currentTime = DateTime.Now;    string ss = (currentTime - oldtime).TotalMilliseconds.ToString();    oldtime = currentTime;    AddText(ss);}void AddText(string strTime){        //在此处使用过:this.isDisposed和this.Disposing进行判定,无法解决            if (this.listView1.InvokeRequired)        {            SetTextCallback d = new SetTextCallback(AddText);                     this.Invoke(d, new object[] { strTime });//此处出现,无法释放问题        }        else        {            string[] str = { listView1.Items.Count.ToString(), "测试", strTime };            ListViewItem item = new ListViewItem(str);            listView1.Items.Add(item);        }  }private void Form1_FormClosing(object sender, FormClosingEventArgs e){      t.Close();//这个地方如果增加一个关闭t.close的话也不行,定时器整个form关闭前没有被关闭!    Thread.Sleep(500);}



程序的主要思想在定时器的状态下,向listview表中写数据,现在问题是,如果程序关闭的时候,定时器不会关闭,这个时候往list中写数据,会提示From已被释放。

在网上也看了很多类似的帖子,主要方法如下:
1、使用this.isDisposed,this.Disposing进行判定
2、在退出的时候增加一个判定的变量,如quitFlag
3、退出的时候增加一个sleep也不行,总是感觉我的from被关闭的时候,定时器还没有被关闭
以上方法都做过测试了,都不行!

以上还有没有更好的方法,目前测试要是能在from关闭前!!完全!!关掉定时器,程序退出就没有问题!
不要给我说用try...catch,这个根本就不是一个解决方法,说Try...catch的不给分,吼吼。



[解决办法]
改成
this.BeginInvoke(d, new object[] { strTime })
[解决办法]
你这种写法是不对的
AddText 方法中
SetTextCallback d = new SetTextCallback(AddText);
this.Invoke(d。。。

也就意味着 this.listView1.InvokeRequired==true时
之前所调用的所有的 AddText方法体(包括其中的 SetTextCallback)都不会释放掉
也就是说 如果this.listView1.InvokeRequired一直保持为true状态的话
会使无数个AddText 不能释放 最后形成无限递归

而 while 不同 它占用的资源不会因为 循环的次数不同 而 变化
建议你用另起线程循环 而不是 另起线程递归
(t.Elapsed+= new System.Timers.ElapsedEventHandler(theout)实际上是另起线程执行)

以上致使 关闭窗口后无法释放掉该方法体 该方法体还需要form窗体资源
所以会出现"访问已经释放的资源"异常
你把 Invoke 改为BeginInvoke 其实资源还是没有释放掉
 但是由于非主线程的异常 不会为主线程捕获到 所以你没有获得异常信息

所以 要做在某一段时间内 无限执行的东西 用 while 不要用 递归
[解决办法]
如楼上,使用递归确实要注意,能不用就别用,用最普通的方法实现
[解决办法]
一步到位

System.Environment.Exit(0);

热点排行