BusyTipOperator——显示提示窗体的实现(二)

前 注:

这是自己平时根据自己需要写的一些小代码,未必对各看官有用。另外,这是根据个人想法而写,未必严谨和符合设计原则,若有任何不妥之处,还请不吝赐教。

说 明:

本文描述一个根据 《BusyTip——显示提示窗体的实现(一) 》中所述思路设计的一个用于显示提示窗体的功能接口的实现。本实现在一个守候线程上循环弹出模态对话框,并封装了触发弹出、关闭对话框事件的接口。

要 点:

1.  TipThread为守候线程,线程方法为TipThreadRun。此方法在循环中等待ShowTipEvent事件,当该事件发生时弹出对话框,并进入阻塞状态;直到对话框关闭,然后线程开始等待下一次ShowTipEvent事件。
2.  Start方法通过触发ShowTipEvent事件来通知TipThread显示对话框,Stop方法通过调用对话框的Close方法来关闭对话框。
3.  Start、Stop与Monitor的Enter、Exit有些相似的特性:Start可以重复进入(效果不变),但调用多少次Start,就必须调用多少次Stop,才能合提示窗体关闭。
4.  可以使用SetProperty方法来设置提示窗体的属性,此方法使用反射与Invoke来实现其功能。BusyTipOperator.Text成员的set访问器是SetProperty("Text",value)的快捷形式。同样的,也可以为进度等其它数据添加类似属性。
5.  当State属性值为Released时,表示此BusyTipOperator对象已经释放其资源,不应再被使用。

未命名

示例:

for (int i = 0; i < 5; ++i)
{
    busytip.Start();
    busytip.Start(string.Format("循环:{0}...",i));
    
    Thread.Sleep(1000);
    busytip.Stop();
    //Thread.Sleep(100);
    busytip.Stop();
}

源 码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.ComponentModel;

namespace CommonLibrary.BusyTip
{
    /// <summary>
    /// 调用委托
    /// </summary>
    public delegate void DelegateInvoke();

    /// <summary>
    /// 不考虑线程安全的设置属性委托
    /// </summary>
    /// <param name="Value">属性值</param>
    public delegate void DelegateSetProperty(string PropertyName, object Value);

    /// <summary>
    /// 提示对象状态的枚举
    /// </summary>
    public enum EnumBusyTipOperatorState
    {
        /// <summary>
        /// 正在显示提示窗体
        /// </summary>
        Show,

        /// <summary>
        /// 空闲,未显示提示窗体
        /// </summary>
        Free,

        /// <summary>
        /// 已释放,无法再显示提示窗体
        /// </summary>
        Released
    };

    /// <summary>
    /// 使用提示窗体的接口
    /// </summary>
    public class BusyTipOperator:IDisposable
    {
        #region Constructor & Destructor

        /// <summary>
        /// 构造函数
        /// </summary>
        public BusyTipOperator(Form tipDialog)
        {
            FrmTip = tipDialog;
            FrmTip.ShowInTaskbar = false;
            FrmTip.Load += new EventHandler(FrmTip_FormLoad);

            ShowTipEvent = new AutoResetEvent(false);
            FrmOpCompletedEvent = new AutoResetEvent(false);

            DelegateSetProperty = new DelegateSetProperty(this.SetProperty);

            TipThread = new Thread(new ThreadStart(this.TipThreadRun));
            TipThread.Start();
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~BusyTipOperator()
        {
            if (!Disposed) Dispose();
        }

        #endregion

        #region Fields

        ///// <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 Form FrmTip;

        /// <summary>
        /// 用于显示提示窗体的线程
        /// </summary>
        private Thread TipThread;

        /// <summary>
        /// 触发显示提示窗体操作的事件
        /// </summary>
        private AutoResetEvent ShowTipEvent;

        /// <summary>
        /// 此事件在窗体操作完成时发出通知
        /// </summary>
        private AutoResetEvent FrmOpCompletedEvent;

        private DelegateSetProperty DelegateSetProperty;

        /// <summary>
        /// 当前提示的状态
        /// </summary>
        private EnumBusyTipOperatorState _State = EnumBusyTipOperatorState.Free;

        /// <summary>
        /// 是否终止显示线程
        /// </summary>
        private bool StopTipThread = false;

        /// <summary>
        /// 非托管资源释放标志
        /// </summary>
        private bool Disposed = false;

        /// <summary>
        /// 锁,用于同步窗体的打开/关闭过程
        /// </summary>
        private object Lock = new object();

        /// <summary>
        /// 统计调用Start的嵌套层数(即当前需要调用Stop的次数)
        /// </summary>
        private int ShowCount = 0;

        #endregion

        #region Properties

        /// <summary>
        /// 当前提示窗体的状态
        /// </summary>
        public EnumBusyTipOperatorState State
        {
            get { return _State; }
        }

        /// <summary>
        /// 提示内容
        /// </summary>
        public string Text
        {
            get
            {
                return FrmTip.Text;
            }
            set
            {
                SetProperty("Text", value);
            }
        }

        /// <summary>
        /// 是否允许取消,此设置项暂时无效,默认为否
        /// </summary>
        public bool CancelEnabled
        {
            get { return false; }
            set
            {
                
            }
        }

        /// <summary>
        /// 父窗体是否可用,此设置项暂时无效,默认为否
        /// </summary>
        public bool ParentEnabled
        {
            get { return false ; }
            set
            {
               
            }
        }

        #endregion

        #region Operator Interface

        /// <summary>
        /// 开始显示提示窗体
        /// </summary>
        public int Start()
        {
            Monitor.Enter(Lock);

            ++ShowCount;

            if (this.State == EnumBusyTipOperatorState.Free)
            {
                _State = EnumBusyTipOperatorState.Show;

                //通过ShowTipEvent事件向TipThread发送信息,使其显示提示窗体
                ShowTipEvent.Set();

                //等待提示窗体显示完成的信号  &  也可以通过以下方式实现:使当前线程挂起,然后在FrmTip_Load中恢复
                FrmOpCompletedEvent.WaitOne();
            }

            Monitor.Exit(Lock);

            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()
        {
            Monitor.Enter(Lock);

            do
            {
                if (ShowCount <= 0) break;
                if (--ShowCount > 0) break;

                _State = EnumBusyTipOperatorState.Free;

                FrmTip.Invoke(new DelegateInvoke(FrmTip.Close));

                FrmOpCompletedEvent.WaitOne();

            } while (false);

            Monitor.Exit(Lock);

            return 1;
        }

        /// <summary>
        /// 设置提示窗体的提示文本
        /// </summary>
        /// <param name="Text"></param>
        public void SetProperty(string PropertyName,object Value)
        {
            if (FrmTip.InvokeRequired)
            {
                FrmTip.Invoke(DelegateSetProperty, PropertyName, Value);
            }
            else
            {
                FrmTip.GetType().InvokeMember(PropertyName, System.Reflection.BindingFlags.SetProperty, null, FrmTip, new object[] { Value });
            }
            }

        #endregion

        #region Innerl Methods

        /// <summary>
        /// 用来显示提示框的守护线程
        /// </summary>
        private void TipThreadRun()
        {
            ShowTipEvent.WaitOne();
            while (!StopTipThread)
            {
                FrmTip.ShowDialog();
                FrmOpCompletedEvent.Set();
                ShowTipEvent.WaitOne();
            }
        }

        /// <summary>
        /// 释放非托管资源
        /// </summary>
        public void Dispose()
        {
            Disposed = true;

            if (this.State == EnumBusyTipOperatorState.Show) Stop();
            StopTipThread = true;
            ShowTipEvent.Set();
            TipThread.Join();
            _State = EnumBusyTipOperatorState.Released;
        }

        /// <summary>
        /// 提示窗体加载完成
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void FrmTip_FormLoad(object sender, EventArgs e)
        {
            FrmOpCompletedEvent.Set();
        }

        #endregion
    }
}
原文地址:https://www.cnblogs.com/yedaoq/p/1704678.html