c# 问题小结

                                                                                          c# 问题小结

     最近做项目,遇到的问题蛮多的额,各种零零碎碎的问题一大箩筐,趁今天有闲暇时间,总结一下这几周遇到的问题。 

     一、Thread类的使用

         ①线程存在多种状态,有时在执行一些操作时,我们需要判断线程的状态,然后在执行相应的操作。

        

 原图出处:http://blog.csdn.net/wangchongcy/article/details/7219880

      例如线程当前的状态为Running,此时我们执行一些操作需要挂起线程,就要判断线程的状态是不是Running状态,

      如果在创建线程时,设置MyThread.IsBackground=true.

      然后判断线程状态时,使用if(MyThread.ThreadState==ThreadState.Running),返回值为false。

      因为此时线程的状态为IsBackground。

      正确的做法如下:

 if ((MyThread.ThreadState & ThreadState.Running) == ThreadState.Running)
   {
       MyThread.Suspend();     
   }
    

    msdn中有详细解释,ThreadState是枚举类型,它允许按位运算组合其变量。

     例如测试线程是否在运行:

   if (myThread.ThreadState & (ThreadState.Stopped | ThreadState.Unstarted)) == 0)
     

    成员名称           说明                          值
    Aborted  线程处于 Stopped状态中。 256
    AbortRequested 已对线程调用了 Thread.Abort方法,但线程尚未收到试图终止它的挂起的                                      System.Threading.ThreadAbortException 128
    Background 线程正作为后台线程执行(相对于前台线程而言)。此状态可以通过设置Thread.IsBackground属性来控制。 4
    Running  线程已启动,它未被阻塞,并且没有挂起的ThreadAbortException 0
    Stopped  线程已停止。 16
    StopRequested 正在请求线程停止。这仅用于内部。  1
    Suspended 线程已挂起。 64
    SuspendRequested 正在请求线程挂起。 2
    Unstarted 尚未对线程调用 Thread.Start方法。 8
    WaitSleepJoin 由于调用 WaitSleep Join,线程已被阻塞。 32

    ②线程退出

     一般情况下,当线程中的函数执行完之后,它会自动结束。

     有时候,我们需要在while(1){ do something...}

     c#中,使用thread.Abort()强制终止线程时,会抛出异常:hreadAbortException

      在《改善C#代码》一书中,有提到过一种做法(类似于设置bool变量):

     创建  CancellationTokenSourcects = new CancellationTokenSource();

     线程中执行的函数改为

 while(true)
   {
      if( cts.Token.IsCancellationRequested)
     {
        return;
     }
     do something;
   }
 

 在必要退出线程的地方,调用cts.Cancel()函数即可,更深入的了解大家可以再交流。

     二、Mdi子窗体相关问题

      子窗体不能重复打开,如果子窗体已经打开,则不再打开;否则是关闭子窗体,再重新打开子窗体。(前提:Mdi父窗体中只允许打开一个子窗体)

      此时:父窗体的属性IsMdiContainer=true;

    

         /*********************************判断是否为子窗口************************************/
        public bool JudgeIsChildForm(string formNameStr)
        {
            bool blIChooseForm = false;
            foreach (Form frm in Application.OpenForms)
            {
                if (formNameStr.Equals(frm.Name))
                {
                    blIChooseForm = true;
                }
            }
            return blIChooseForm;
        }
        /*******************************************窗口显示************************************/
        public void ShowAnyFormInMain(string FormName)
        {
            bool blIsChooseForm = false;
            blIsChooseForm = JudgeIsChildForm(FormName);
            if (!blIsChooseForm)
            {
                foreach (Form frm in this.MdiChildren)
                {
                    if (!frm.IsDisposed)
                    {
                        frm.Close();
                    }
                }
            
                switch (FormName)
                {
                    case "ConnectEquipmentForm":
                        {
                            childForm = new ConnectEquipmentForm();
                        }
                        break;

                       ...
                        
                    default:
                        break;
                }
                if (childForm != null)
                {
                    childForm.MdiParent = this;
                    childForm.ControlBox = true;
                    //childForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable;
                    childForm.Resize +=new EventHandler(ChildForm_Resize);
                    childForm.WindowState = this.WindowState;
                    childForm.MaximizeBox = false;
                    childForm.MinimizeBox = false;
                    childForm.StartPosition = FormStartPosition.Manual;//固定窗体的起始位置,否则子窗体每次启动的位置都有所不同。
                    childForm.Activate();
                    childForm.Show();
                }
        }
}

     然后在按钮下只需要调用ShowAnyFormInMain("窗体名称");

 无法访问一个已释放的窗体

         如上 中的做法,假如我们在一个button下打开了一个子窗体,然后再关闭这个子窗体。再按这个button再次打开子窗体,可能会遇到问题

        “无法访问一个已释放的窗体

         这说明:子窗体的资源未及时释放,而又再次调用子窗体来做一些事。

        例如我的程序中,按一个按钮,打开一个子窗体,而后有读取一些数据使用Invoke显示到子窗体界面上。

         捕获异常创建窗体句柄之前,不能在控件上调用InvokeBeginInvoke”

       当时我尝试了一些做法, // 防止在窗口句柄初始化之前就走到下面的代码  

       

       1) 防止在窗口句柄初始化之前就执行到下面的代码 

      

while (!this.IsHandleCreated) 
{  
          ; 
 }
      2).
if(!this.IsHandleCreated)
    {
        this.CreateHandle(); 
    }

   第一种方法出现了死等的情况;第二种方法捕获到异常:无法访问一个已释放的窗体

    大家可以看到此时我们使用了childForm来表示子窗体(我的程序中也是如此),在子窗体关闭时,childForm并未Close,这才是产生问题的根本原因。

   因此在父窗体的Form_Closing事件中,要判断

if(childForm!=null)//在这里不关闭窗体,第二次打开子窗体时,系统无法访问到一个已经释放的窗体。
   {
            childForm.Close();
    }
   有必要的话,在new子窗体时,也加强判断:   

if (childForm == null || childForm.IsDisposed)
  {
                         childForm = new XXForm();
  }
  (End!)

    


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值