使用线程新建WPF窗体(公用进度条窗体)

简介: 使用线程新建窗体 项目中需要一个公用的进度条窗体.大家知道在wpf中,有两个线程,一个是UI线程,另一个是监听线程(一直监听用户的输入).如果我们后台有阻塞UI线程的计算存在,那么界面上的比如进度条什么动态的UI都会被因为阻塞而静止不动.

使用线程新建窗体

项目中需要一个公用的进度条窗体.大家知道在wpf中,有两个线程,一个是UI线程,另一个是监听线程(一直监听用户的输入).如果我们后台有阻塞UI线程的计算存在,那么界面上的比如进度条什么动态的UI都会被因为阻塞而静止不动.

所以我的想法就是新起一个线程来负责进度条窗体的显示与关闭,具体实现代码如下:

 

   private static Thread th;
        /// <summary>
        /// 显示进度条 线程
        /// </summary>
        /// <param name="msg">进度条界面需要显示的文字</param>
        /// <param name="sleep">增加进度条存在的延迟时间,单位为毫秒</param>
        public static void BeginProgressBar(string msg, int sleep)
        {
            try
            {
                if (th == null || th.ThreadState == ThreadState.Aborted)
                {
                    th = new Thread(new ThreadStart(() =>
                   {
                       WinProgressBar win = new WinProgressBar();
                       win.Tips = msg;
                       win.Topmost = true;
                       win.Show();
                       System.Windows.Threading.Dispatcher.Run();
                   }));

                    th.SetApartmentState(ApartmentState.STA);
                    th.IsBackground = true;
                }
                if (th.ThreadState != ThreadState.Background || th.ThreadState == ThreadState.Unstarted || th.ThreadState != ThreadState.Running)
                {
                    th.Start();
                }
            }
            catch (Exception)
            {
                th = new Thread(new ThreadStart(() =>
                {
                    WinProgressBar win = new WinProgressBar();
                    win.Tips = msg;
                    win.Topmost = true;
                    win.Show();
                    System.Windows.Threading.Dispatcher.Run();
                }));

                th.SetApartmentState(ApartmentState.STA);
                th.IsBackground = true;
                th.Start();
            }
            Thread.Sleep(sleep);
        }

        /// <summary>
        /// 结束进度条
        /// </summary>
        public static void EndProgressBar()
        {
            if (th.IsAlive)
                th.Abort();
        }

 

呵呵,大家仔细分析下代码看有什么问题没有?而你们又有什么好的解决方案没有?

在使用过程中发现一个很严重的问题,出现一个进度条窗体,系统内存就会增大一点,到最后要么卡死,要么自动退出.

     原来在多线程程序运行中,由用户取消操作是一种非常常见的场景,比如用户使用windows资源管理器在当前文件夹中搜索文件时,可以通过点击其它文件夹而取消搜索。
中途停止一个线程的执行,通常用Thread.Abort方法,但这种方式会造成程序涉及的数据完整性受到破坏,线程所占用的一些系统资源(比如文件句柄等)也可能无法完成。比较合理的方式是外界提出"取消操作"的请求,然后由线程自身来决定如何处理这一请求。
在设计多线程程序时,可设置一个用于接收外部取消消息的属性,然后在线程函数中分阶段地检测这一属性,每个阶段的检查点由软件开发者确定,并且决定线程如何优雅退出。

所以对上述代码进行了改进

首先设置一个公共变量:

 public static bool IsClsoeProgeressBar = true;

然后在进度条窗体中实时读这个数据

 

/// <summary>
    /// WinProgressBar.xaml 的交互逻辑
    /// </summary>
    public partial class WinProgressBar : Window
    {
        public string Tips { get; set; }

        DispatcherTimer timer;
        public WinProgressBar()
        {
            InitializeComponent();

            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromMilliseconds(200);
            timer.Tick += new EventHandler(timer_Tick);
            timer.IsEnabled = true;

            this.Topmost = true;
            //this.Loaded += delegate
            //{
            //    if (this.Tips != "")
            //        tbTips.Text = this.Tips;
            //};
        }

        void timer_Tick(object sender, EventArgs e)
        {
            if (Common.CommWindow.IsClsoeProgeressBar)
            {
                if (this.Visibility == Visibility.Visible)
                {
                    progressBar1.IsIndeterminate = false;
                    this.Hide();
                }
            }
            else
            {
                if (this.Visibility != Visibility.Visible)
                {
                    progressBar1.IsIndeterminate = true;
                    this.Show();
                }           
            }
        }
    }

 

然后在系统加载的时候,创建这个进度条窗体

   try
            {
                Thread th = new Thread(new ThreadStart(() =>
                {
                    WinProgressBar win = new WinProgressBar();

                   // win.Tips = msg;
                    win.Show();

                    System.Windows.Threading.Dispatcher.Run();

                }));

                th.SetApartmentState(ApartmentState.STA);
                th.IsBackground = true;

                th.Start();
            }
            catch (Exception)
            {
            }

我们只需改变公共变量来控制窗体的显示与隐藏

         /// <summary>
        /// 显示进度条 线程
        /// </summary>
  
        public static void BeginProgressBar()
        {
            IsClsoeProgeressBar = false;
        }

        /// <summary>
        /// 结束进度条
        /// </summary>
        public static void EndProgressBar()
        {
            //cts.Cancel();
            IsClsoeProgeressBar = true;
        }

还有一个比较好的方法:

 #region Methods

        /// <summary>
        /// 一个耗时的任务
        /// </summary>
        private void BigTask()
        {
            Thread.Sleep(3000);
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            MyProgressBar(BigTask);
        }

        private void MyProgressBar(Action mywork)
        {
            var worker = new BackgroundWorker();
            var window = new BusyWindow();
            worker.DoWork += (s, e2) => { mywork(); };
            worker.RunWorkerCompleted += (s, e2) =>
            {
                MessageBox.Show("任务已经完成");
                window.Close();
            };
            worker.RunWorkerAsync();
            window.Show();
        }

        #endregion

这个由网友热情的沙漠提供,也很不错,大家可以参考下

 

目录
相关文章
|
安全 Java
【JavaSE专栏76】三态和五态,线程的不同状态:新建、运行、状态、阻塞、等待、计时等待状态
【JavaSE专栏76】三态和五态,线程的不同状态:新建、运行、状态、阻塞、等待、计时等待状态
100 0
|
5月前
|
Java
【技术解码】Java线程的五味人生:新建、就绪、运行、阻塞与死亡的哲学解读!
【6月更文挑战第19天】Java线程生命周期如同人生旅程,经历新建、就绪、运行、阻塞至死亡五阶段。从`new Thread()`的诞生到`start()`的蓄势待发,再到`run()`的全力以赴,线程在代码中奔跑。阻塞时面临挑战,等待资源释放,最终通过`join()`或中断结束生命。线程的每个状态转变,都是编程世界与哲思的交汇点。
37 1
WPF控件和窗体一起放大一起缩小
WPF控件和窗体一起放大一起缩小
233 0
|
C# 容器
WPF框架下,窗体的嵌套显示
WPF框架下,窗体的嵌套显示
217 0
|
C# 数据库 UED
C#-WPF ProgressBar进度条
进度条常用在加载,下载,导出一些比较耗时的地方,利用进度条能让用户看到实时进展,能有更好的用户体验……
594 0
|
C# 索引
WPF实用指南二:移除窗体的图标
原文:WPF实用指南二:移除窗体的图标 WPF没有提供任何功能来移除窗体上的icon图标。一般的做法是设置一个空白的图标,如下图1: 这种做法在窗体边框与标题之间仍然会保留一片空白。
1250 0
|
人工智能 搜索推荐 C#
Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
结合Photoshop和WPF,共同创建一个矢量的个性化进度条。
550 0
Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
|
前端开发 C#
WPF 介绍一种在MVVM模式下弹出子窗体的方式
原文:WPF 介绍一种在MVVM模式下弹出子窗体的方式 主要是通过一个WindowManager管理类,在window后台代码中通过WindowManager注册需要弹出的窗体类型,在ViewModel通过WindowManager的Show方法,显示出来。
2341 0
|
C#
WPF下载远程文件,并显示进度条和百分比
原文:WPF下载远程文件,并显示进度条和百分比 WPF下载远程文件,并显示进度条和百分比 1、xaml  2、CS程序 using System; using System.
1888 0
|
C#
WPF去除窗体边框及白色边框
原文:WPF去除窗体边框及白色边框        0
1463 0