ts = new Thread(new ThreadStart(ShowProgressForm));
                ts.IsBackground = true;
                ts.SetApartmentState(ApartmentState.STA);
                ts.Start();                this.LoadPeriods(this, new EventArgs());                //因为线程启动进度条窗体是需要时间的,所以下面的代码等待进度条窗体启动。
                while (fpb == null && fpb.Visible!=true)
                {
                    Thread.Sleep(10);
                }
                Thread.Sleep(40);
                //因为是.ShowDialog()启动,所以需要人工Dispose窗体
                if (fpb != null)
                {
                    fpb.SafeBeginInvoke(d => d.Close());        
                    fpb.SafeBeginInvoke(d => d.Dispose());      
                }fpb是类里面的私有变量,是ts里面启动的进度条窗体        private void ShowProgressForm()
        {
            if (fpb != null)
            {
                fpb.SafeBeginInvoke(d => d.Close());
                fpb.SafeBeginInvoke(d => d.Dispose());
            }
            
            //Application.EnableVisualStyles();
            fpb = new FormProgressBar("提示...");
            fpb.ProgressStyle = ProgressBarStyle.Marquee;
            fpb.DisplayPercent = false;
            fpb.ShowDialog();    
        }

解决方案 »

  1.   

    创建完成后,在窗体的tag放个值。检测那个值。
      

  2.   

    莫非我得在窗体里面写个事件,然后主线程触发这个事件来关闭窗体?
    但是貌似也没解决线程还没启动完成,主线程就要求关闭窗体的问题呀!

    哪个线程启动的窗体,你让它自己去关闭
    加个全局变量,主线程修改这个变量,通知线程要关闭窗体了
    线程检测到这个变量,再去看看窗体是否已经打开了,打开了就关闭,没打开就不用关闭了
    涉及到UI的问题,能不跨线程操作最好不要,否则又要加委托,怪麻烦的.现在的问题就是我没法知道窗体是不是完整打开了,当fpb!=null的时候,执行Close依然可能报错。你有什么办法解决这个问题?
      

  3.   


    是否奇葩不好说,进度条窗体本来就是应该由主窗体通知关闭的。现在的问题是,主窗体通知线程里面的窗体Close的时候,窗体还没有CreatHandle完毕,导致报错,你明白我的意思了吧
      

  4.   


    是否奇葩不好说,进度条窗体本来就是应该由主窗体通知关闭的。现在的问题是,主窗体通知线程里面的窗体Close的时候,窗体还没有CreatHandle完毕,导致报错,你明白我的意思了吧
    主窗体应该只负责通知,然后弹出窗体自己的逻辑执行完了自己关闭,而不是主窗体直接去操作
    否则就变成主窗体依赖子窗体的当前状态,你要传的参数多了去了
      

  5.   

    嗯,有道理,怎么通知线程里面的窗体改关闭呀?我看好多例子用的是while(true)有没有别的方法?或者委托?主线程里面定义一个事件,让子线程订阅?有没有简洁代码能参考的,太复杂的话,还不如访问子窗体的属性来的省事
      

  6.   

    顺便问问诸位,即使是主线程通知子线程关闭窗体,就一定能确保close在窗体完成CreatHandle之后才执行吗?如果通知早了,会不会也发生一楼的情况?
      

  7.   

    可以在子窗体中用timer来判断,不用while(true)
    或者,你子窗体本来就是在线程中开启的,线程开启了子窗体后不要不管了,让它while(true)等待主窗体指令
    如果主窗体给的太早,线程就可以直接退出了,而不用先开窗体再关窗体.
      

  8.   

    比如在主线程中设置个public bool IsShowing变量
    线程中
    bool IsShown=false;
    while(IsShowing)
    {
    if(! IsShown)
    {
    form2.show();
    }
    thread.sleep(100);
    }
    if(IsShown)
    {
    form2.close();
    }
    线程先判断主窗体是否要打开子窗体,如果线程启动后,主窗体逻辑已经执行完毕,不需要开窗体了,就直接退出.
    如果线程启动后,依然要求打开子窗体,那么打开子窗体,同时加个变量标识子窗体已经打开过,不要再打开了
    如果主窗体通知关闭,那么退出循环,关闭窗体.
      

  9.   


    这个主意也不错,不过那个子线程的进度条窗体因为要采用滚动效果,貌似不能用show,只能用showdialog所以,没法在线程里面使用while循环大概还得用委托或者事件吧,还有什么好主意吗?谢谢
      

  10.   


    子窗体是个进度条显示,现在的问题是主线程在子线程的窗体还没有创建完毕的时候,就去操作close,导致报错。我尝试用visible=true属性,或者自己搞个属性,应该都可以判断窗体是否创建完毕。也能解决这个问题,但是感觉不太好。我觉得这个问题虽然概率很低,但是如果做一个严谨的进度条窗体的话,应该有什么专业一点的办法来防止过早通知子窗体执行close吧
      

  11.   

    或者谁能把Close方法里面的那个GetState给搞出来?通过这个判断貌似更专业而且更唬人吧下面是close方法的代码
    public void Close()
    {
        if (base.GetState(0x40000))
        {
            throw new InvalidOperationException(SR.GetString("ClosingWhileCreatingHandle", new object[] { "Close" }));
        }
        if (base.IsHandleCreated)
        {
            this.closeReason = CloseReason.UserClosing;
            base.SendMessage(0x10, 0, 0);
        }
        else
        {
            base.Dispose();
        }
    }
      

  12.   


    子窗体是个进度条显示,现在的问题是主线程在子线程的窗体还没有创建完毕的时候,就去操作close,导致报错。我尝试用visible=true属性,或者自己搞个属性,应该都可以判断窗体是否创建完毕。也能解决这个问题,但是感觉不太好。我觉得这个问题虽然概率很低,但是如果做一个严谨的进度条窗体的话,应该有什么专业一点的办法来防止过早通知子窗体执行close吧
    严谨的进度条窗体应该是由子线程去执行操作的...(比如复制)..然后进度条实时更新..这样就一定会有一个变量去保存进度条的进行状况..你可以拿那个变量来判断...不过现在我也不清楚你的进度条是怎么写的...