none
线程启动窗体 RRS feed

答案

  • 你好!
         明白你的需求了,你是不想中断当前的程序,然后还想显示一个“请稍等”的窗体来提醒用户程序正在处理一些操作吧,这个不用多线程,也不用ShowDialog(),先设置TopMost=true,然后Show()就可以了:

         Form2 form2 = new Form2();
         form2.TopMost = true;
         form2.Show();

         操作完毕再关闭这个窗体就可以了!
    周雪峰
    2009年10月24日 12:05
    版主

全部回复

  • 我前阵子写的一个用于繁忙提示的类,在单独的线程上显示对话框

    /// <summary>
        /// 调用委托
        /// </summary>
        public delegate void InvokeDelegate();
    
        /// <summary>
        /// 用于保存属性设置信息的结构
        /// </summary>
        public struct PropertySet
        {
            /// <summary>
            /// 要设置的属性名称
            /// </summary>
            public String Member;
    
            /// <summary>
            /// 属性的值
            /// </summary>
            public object[] Value;
    
            /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="Member">成员标识符</param>
            /// <param name="Value">值</param>
            public PropertySet(String Member, object Value)
            {
                this.Member = Member;
                this.Value = new object[1] { Value };
            }
        }
    
        /// <summary>
        /// 使用提示窗体的接口
        /// </summary>
        public class BusyTip
        {
            #region 单例
    
            static Singleton<BusyTip> Singleton;
    
            public static BusyTip Instance
            {
                get
                {
                    if (Singleton == null) Singleton = new Singleton<BusyTip>();
                    return Singleton.Instance;
                }
            }
    
            #endregion
    
            #region 类型
    
            /// <summary>
            /// 不考虑线程安全的设置属性委托
            /// </summary>
            /// <param name="Value">属性值</param>
            public delegate void SetPropertyUnSafeDelegate(string PropertyName, object Value);
    
            /// <summary>
            /// 提示对象状态的枚举
            /// </summary>
            public enum StateEnum 
            { 
                /// <summary>
                /// 正在显示提示窗体
                /// </summary>
                Show, 
    
                /// <summary>
                /// 空闲,未显示提示窗体
                /// </summary>
                Free, 
    
                /// <summary>
                /// 已释放,无法再显示提示窗体
                /// </summary>
                Released
            };
    
            #endregion
    
            #region 数据
    
            ///// <summary>
            ///// 显示的图片
            ///// </summary>
            //public String _PictureAddress;
    
            ///// <summary>
            ///// 是否允许取消
            ///// </summary>
            //public bool _CancelEnabled = true;
    
            ///// <summary>
            ///// 父窗体是否可用
            ///// </summary>
            //public bool _ParentEnabled = false;
    
            ///// <summary>
            ///// 标记是否终止守护线程
            ///// </summary>
            //public bool StopTipThread = false;
    
            /// <summary>
            /// 提示窗体
            /// </summary>
            private FrmBusyTip FrmTip;
    
            /// <summary>
            /// 用于显示提示窗体的线程
            /// </summary>
            private Thread TipThread;
    
            /// <summary>
            /// 触发显示提示窗体操作的事件
            /// </summary>
            private AutoResetEvent ShowTipEvent;
    
            /// <summary>
            /// 当前提示的状态
            /// </summary>
            public StateEnum State = StateEnum.Free;
    
            /// <summary>
            /// 是否终止显示线程
            /// </summary>
            public bool StopTipThread = false;
    
            /// <summary>
            /// 非托管资源释放标志
            /// </summary>
            private bool Disponsed = false;
    
            /// <summary>
            /// 关闭事件
            /// </summary>
            private AutoResetEvent _CloseEvent = new AutoResetEvent(false);
    
            /// <summary>
            /// 此事件在窗体操作完成时发出通知
            /// </summary>
            private AutoResetEvent FrmOpCompletedEvent = new AutoResetEvent(false);
    
            private object Lock = new object();
    
            #endregion
    
            #region 属性
    
            /// <summary>
            /// 提示内容
            /// </summary>
            public string Text
            {
                get
                {
                    return FrmTip.Text;
                }
                set
                {
                    if (FrmTip.InvokeRequired)
                    {
                        FrmTip.Invoke(new SetPropertyUnSafeDelegate(this.SetPropertyUnSafe), "Text", value);
                    }
                    else
                    {
                        FrmTip.Text = value;
                    }
                    
                }
            }
    
            /// <summary>
            /// 图片地址
            /// </summary>
            public string PictureAddress
            {
                get { return FrmTip.PictureAddress; }
                set
                {
                    if (FrmTip.InvokeRequired)
                    {
                        FrmTip.Invoke(new SetPropertyUnSafeDelegate(this.SetPropertyUnSafe), "PictureAddress", value);
                    }
                    else
                    {
                        FrmTip.PictureAddress = value;
                    }
                }
            }
    
            /// <summary>
            /// 是否允许取消
            /// </summary>
            public bool CancelEnabled
            {
                get { return FrmTip.CancelEnabled; }
                set
                {
                    if (FrmTip.InvokeRequired)
                    {
                        FrmTip.Invoke(new SetPropertyUnSafeDelegate(this.SetPropertyUnSafe), "CancelEnabled", value);
                    }
                    else
                    {
                        FrmTip.CancelEnabled = value;
                    }
                }
            }
    
            /// <summary>
            /// 父窗体是否可用
            /// </summary>
            public bool ParentEnabled
            {
                get { return FrmTip.ParentEnabled ; }
                set
                {
                    if (FrmTip.InvokeRequired)
                    {
                        FrmTip.Invoke(new SetPropertyUnSafeDelegate(this.SetPropertyUnSafe), "ParentEnabled", value);
                    }
                    else
                    {
                        FrmTip.ParentEnabled = value;
                    }
                }
            }
    
            /// <summary>
            /// 关闭事件
            /// </summary>
            private AutoResetEvent CloseEvent
            {
                get { return _CloseEvent; }
            }
    
            #endregion
    
            #region 构造析构
    
            /// <summary>
            /// 构造函数
            /// </summary>
            public BusyTip()
            {
                FrmTip = new FrmBusyTip();
                FrmTip.ShowInTaskbar = false;
                FrmTip.Load += new EventHandler(TipLoadCompleted);
                FrmTip.FormClosed += new FormClosedEventHandler(TipCloseCompleted);
    
                ShowTipEvent = new AutoResetEvent(false);
                TipThread = new Thread(new ThreadStart(this.TipThreadRunner));
                TipThread.SetApartmentState(ApartmentState.STA);
                TipThread.Start();
            }
    
    
            /// <summary>
            /// 构造函数:通过传入任意数量PropertySet结构,在构造时即可对任意成员进行初始化
            /// </summary>
            /// <param name="SetValueTasks"></param>
            public BusyTip(params PropertySet[] SetValueTasks)
                : this()
            {
                Type MyType = this.GetType();
                foreach (PropertySet Task in SetValueTasks)
                {
                    try
                    {
                        MyType.InvokeMember(Task.Member, System.Reflection.BindingFlags.SetProperty, null, this, Task.Value);
                    }
                    catch (Exception Ex)
                    {
                        Console.WriteLine(Ex.ToString());
                    }
                }
            }
    
            /// <summary>
            /// 析构函数
            /// </summary>
            ~BusyTip()
            {
                if (!Disponsed) Disponse();
            }
    
            #endregion
    
            #region 方法
    
            /// <summary>
            /// 用来显示提示框的守护线程
            /// </summary>
            private void TipThreadRunner()
            {
                ShowTipEvent.WaitOne();
                while (!StopTipThread)
                {
                    FrmTip.ShowDialog();
                    ShowTipEvent.WaitOne();
                }
            }
    
            /// <summary>
            /// 提示窗体加载完成
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void TipLoadCompleted(object sender, EventArgs e)
            {
                State = StateEnum.Show;
    
                Console.WriteLine("Form Load Complete");
                FrmOpCompletedEvent.Set();
            }
    
            /// <summary>
            /// 提示窗体关闭完成
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            void TipCloseCompleted(object sender,FormClosedEventArgs e )
            {
                State = StateEnum.Free;
    
                Console.WriteLine("Form Close Complete");
    
    
                FrmOpCompletedEvent.Set();
            }
    
            /// <summary>
            /// 开始显示提示窗体
            /// </summary>
            public int Start()
            {
                Monitor.Enter(Lock);
    
                if (this.State == StateEnum.Free)
                {
                    //通过ShowTipEvent事件向TipThread发送信息,使其显示提示窗体
                    ShowTipEvent.Set();
    
                    //等待提示窗体显示完成的信号
                    FrmOpCompletedEvent.WaitOne();
    
                    Monitor.Exit(Lock);
                }
                else
                {
                    Monitor.Exit(Lock);
    
                    System.Diagnostics.Debug.Assert(false, "提示窗体正在显示或已销毁,无法再次显示!");
                    return -1;
                }
    
                return 1;
            }
    
            /// <summary>
            /// 开始显示提示窗体并在其中显示指定的提示文本
            /// </summary>
            /// <param name="Text"></param>
            /// <returns></returns>
            public int Start(string Text)
            {
                this.Text = Text;
                return Start();
            }
    
            /// <summary>
            /// 终止显示提示窗体
            /// </summary>
            public int Stop()
            {
                if (this.State != StateEnum.Show)
                {
                    return 0;
                }
    
                Monitor.Enter(Lock);
    
                if (this.State == StateEnum.Show)
                {
                    //
                    FrmTip.EndShow();
                    FrmOpCompletedEvent.WaitOne();
    
                    Monitor.Exit(Lock);
                }
                else
                {
                    Monitor.Exit(Lock);
                    return 0;
                }
    
                return 1;
            }
    
            /// <summary>
            /// 设置提示窗体的提示文本
            /// </summary>
            /// <param name="Text"></param>
            private void SetPropertyUnSafe(string PropertyName,object Value)
            {
                FrmTip.GetType().InvokeMember(PropertyName, System.Reflection.BindingFlags.SetProperty, null, FrmTip, new object[] { Value });
            }
    
            /// <summary>
            /// 释放非托管资源
            /// </summary>
            public void Disponse()
            {
                if (this.State == StateEnum.Show) Stop();
                StopTipThread = true;
                ShowTipEvent.Set();
                TipThread.Join();
                State = StateEnum.Released;
    
                Disponsed = true;
            }
    
            #endregion
        }
    2009年10月23日 9:23
  • 比较乱,看BusyTip类即可。

    此类并非全无Bug,当连续的Stop、Start时会出异常,我也还没搞明白....
    2009年10月23日 9:28
  • 你好!
         这样试试:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;
    
    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                Thread t=new Thread(MyShowDialog);
                t.Start();
            }
    
            private void MyShowDialog()
            {
                Form1 form1 = new Form1();
                form1.ShowDialog();
            }
        }
    }


    周雪峰
    2009年10月23日 10:40
    版主
  • 对不起可能你明白我的意思
    我的意思是
    同样的代码
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.Threading;

    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                Thread t=new Thread(MyShowDialog);
                t.Start();
            }

            private void MyShowDialog()
            {
                Form2 form1 = new Form2();
                form2.ShowDialog();
            }
        }
    }
    弹出Form2时Form1还是可以操作的
    因为不在一个线程上么
    两个窗体都是可用的
    所以我想让Form1窗体点不找
    应为我Form1上还有程序在运行
    Form2只是告诉"请稍等"
    可是这时候Form1还是可以使用的
    这样导致你一点击Form1
    程序就白了

    2009年10月23日 15:02
  • 能把你的原始代码给我一份么
    你的代码在我机器上运行不了
    mn20__@163.com
    是两个下划线
    谢谢了
    2009年10月23日 15:55
  • 每个线程都有自己的消息循环,ShowDialog只能启动一个模态循环。
    建议重写你的代码,把界面逻辑从工作线程中移出。


    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年10月23日 16:38
    版主
  • 你好!
         明白你的需求了,你是不想中断当前的程序,然后还想显示一个“请稍等”的窗体来提醒用户程序正在处理一些操作吧,这个不用多线程,也不用ShowDialog(),先设置TopMost=true,然后Show()就可以了:

         Form2 form2 = new Form2();
         form2.TopMost = true;
         form2.Show();

         操作完毕再关闭这个窗体就可以了!
    周雪峰
    2009年10月24日 12:05
    版主