码迷,mamicode.com
首页 > 编程语言 > 详细

C# 多线程窗体的创建

时间:2016-08-05 21:26:37      阅读:328      评论:0      收藏:0      [点我收藏+]

标签:

  从目前已经在项目中工作将近一个月来的情况来看,凡是费时的操作,基本上都要用到多线程的等待窗体、进度提示窗体等实时显示动态的进度信息。而如果直接在主线程的窗体上实时更新信息,就会造成更新太快或者太慢而出现的进程假死现象。为了缓解这些情况,本文就参考一些文章,把他们的智慧总结于此。希望对大家有所帮助。

一、多线程中创建等待窗体

   在winform程序开发中,计算机经常会执行一些比较耗时的任务,如大量数据的查询操作、较为复杂的业务处理等,这些任务往往需要耗时几秒到几十秒钟的时间,在这些任务执行期间winform程序窗体不再响应任何鼠标和键盘事件,出现假死状态,用户体验很差。

  一个比较好的解决办法是,在这些任务执行期间在界面前端显示一个等待窗体,告诉用户任务正在执行中。

1.1 开发等待窗体

技术分享

窗体中有一个PictureBox控件和两个Lable控件,PictureBox控件的Image属性为一张动态图片。

技术分享
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;
using NavManager.Common;

namespace NavManager.Utils
{
    public partial class WaitForm : Form
    {
        public WaitForm()
        {            
            InitializeComponent();
            SetText("");
        }

        private delegate void SetTextHandler(string text);
        public void SetText(string text)
        {
            if (this.label2.InvokeRequired)
            {
                this.Invoke(new SetTextHandler(SetText), text);
            }
            else
            {
                this.label2.Text = text;
            }
        }
    }
}
等待窗体源码

 

1.2 提供访问等待窗体的接口

编写类WaitFormService

技术分享
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace NavManager.Utils
{
    /// <summary>
    /// Using Singleton Design Pattern
    /// </summary>
    public class WaitFormService
    {
        public static void CreateWaitForm()
        {
            WaitFormService.Instance.CreateForm();
        }

        public static void CloseWaitForm()
        {
            WaitFormService.Instance.CloseForm();
        }

        public static void SetWaitFormCaption(string text)
        {
            WaitFormService.Instance.SetFormCaption(text);
        }

        private static WaitFormService _instance;
        private static readonly Object syncLock = new Object();

        public static WaitFormService Instance
        {
            get 
            {
                if (WaitFormService._instance == null)
                {
                    lock (syncLock)
                    {
                        if (WaitFormService._instance == null)
                        {
                            WaitFormService._instance = new WaitFormService();
                        }
                    }
                }
                return WaitFormService._instance;
            }
        }

        private WaitFormService()
        {
        }

        private Thread waitThread;
        private WaitForm waitForm;

        public void CreateForm()
        {
            if (waitThread != null)
            {
                try
                {
                    waitThread.Abort();
                }
                catch (Exception)
                {
                }
            }

            waitThread = new Thread(new ThreadStart(delegate()
            {
                waitForm = new WaitForm();
                Application.Run(waitForm);
            }));
            waitThread.Start();
        }

        public void CloseForm()
        {
            if (waitThread != null)
            {
                try
                {
                    waitThread.Abort();
                }
                catch (Exception)
                {
                }
            }
        }

        public void SetFormCaption(string text)
        {
            if (waitForm != null)
            {
                try
                {
                    waitForm.SetText(text);
                }
                catch (Exception)
                {
                }
            }
        }

    }
}
WaitFormService Class Code

 

1.3 使用WaitFormService提供的接口

技术分享
 try
    {
        WaitFormService.CreateWaitForm();
        Assembly asmb = Assembly.GetExecutingAssembly();
        Object obj = asmb.CreateInstance(className);
        Form frm = obj as Form;
        this.ShowMenu(frm);
        WaitFormService.CloseWaitForm();
    }
    catch (Exception ex)
    {
        WaitFormService.CloseWaitForm();
    }
接口的使用

 

 

二、透明的数据加载进度条

建立一个公用的进度条控件,每次加载较慢的时候使用以改进用户体验。通过启用新线程的方式来进行调用。

步骤如下:

(1)建立一个单独的窗体,包含一个进度条控件。

设置进度条的Style为ProgressBarStyle.Marquee;

增加一属性(LoadCompleted)标示加载是否完成。

(2)在其它窗体中通过开启新线程进行调用。

技术分享
public partial class UcLoadData_ShowMarqueeProcess : UserControl
    {
        public static FrmMarqueeProcess xf;
        public static event EventHandler onLoadFinished;

        public UcLoadData_ShowMarqueeProcess()
        {
            InitializeComponent();
        }

        private void btnFill_Click(object sender, EventArgs e)
        {
            int iEnd = 10000;
            Thread t = new Thread(new ThreadStart(ShowProcess));
            t.Start();

            for (int i = 0; i < iEnd; i++)
            {
                string strContent = string.Format("this is the {0}th record", i);
                this.lstContent.Items.Add(strContent);
            }

            onLoadFinished += new EventHandler(LoadFinish);
            if (onLoadFinished != null)
                onLoadFinished.Invoke(sender, e);

            while (!xf.LoadCompleted)
                Application.DoEvents();

            t.Abort();
        }
        private static void ShowProcess()
        {
            xf = new FrmMarqueeProcess();
            xf.ShowDialog();
        }

        private static void LoadFinish(object sender, EventArgs e)
        {
            xf.LoadCompleted = true;
        }
    }
透明进度条源码

运行结果如下:

 技术分享

 

 

 

参考文章

1. 飘落纸飞机C# winform 多线程中创建等待窗体,2011。

2. heoo多线程之进度条,  2013.

C# 多线程窗体的创建

标签:

原文地址:http://www.cnblogs.com/arxive/p/5742755.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!