BackgroundWorker实现暂停操作

          当我们处理耗时操作时,为了避免单线程处理时界面的假死状态,我们往往选择将耗时操作放到后台线程里处理,后台线程处理完毕之后通知主线程执行成功。.net中的BackgroundWorker组件实现了后台线程操作的封装,使用起来非常便捷。具体使用的例子园子里有好几篇文章,感兴趣的朋友可以搜一下。今天我主要谈一下,如何在程序执行的过程中“暂停”后台线程的操作。大概的思路是设置一个标志,当用户请求暂停操作时,将该标志设成true,否则未false。然后在后台线程的操作中,在适当的位置检查该标志,如果为true,则暂停后台线程的操作。有一点需要说明的是,这里的“暂停”并不是调用Thread.CurrentThread.Suspend()或Monitor.Wait(object)实现的,这里采用了一种替代方案

 

ContractedBlock.gif ExpandedBlockStart.gif 替代方案
//当需要暂停操作时,阻止后台线程继续执行
while (isSuspend)
ExpandedBlockStart.gifContractedBlock.gif
{
    Thread.Sleep(
50);
}

 

           由于原理非常简单,废话不多说,直接看代码:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
 1using System;
 2using System.Collections.Generic;
 3using System.ComponentModel;
 4using System.Data;
 5using System.Drawing;
 6using System.Text;
 7using System.Windows.Forms;
 8using System.Threading;
 9
10namespace BackgroundWorkerDemo
11ExpandedBlockStart.gifContractedBlock.gif{
12    public partial class Form1 : Form
13ExpandedSubBlockStart.gifContractedSubBlock.gif    {
14        private bool isSuspend;//是否需要暂停操作
15
16        public Form1()
17ExpandedSubBlockStart.gifContractedSubBlock.gif        {
18            InitializeComponent();
19        }

20
21        private void btnRunBgWorker_Click(object sender, EventArgs e)
22ExpandedSubBlockStart.gifContractedSubBlock.gif        {
23            btnRunBgWorker.Enabled = false;
24
25            BackgroundWorker bgWorker = new BackgroundWorker();
26            bgWorker.WorkerSupportsCancellation = true;
27            bgWorker.WorkerReportsProgress = true;
28            bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
29            bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
30            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
31            bgWorker.RunWorkerAsync();
32        }

33
34        void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
35ExpandedSubBlockStart.gifContractedSubBlock.gif        {
36            MessageBox.Show("后台操作结束!");
37            btnRunBgWorker.Enabled = true;
38        }

39
40        void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
41ExpandedSubBlockStart.gifContractedSubBlock.gif        {
42            //显示进度信息
43            lblProgress.Text = string.Format("当前进度:{0}%", e.ProgressPercentage.ToString());
44            progressBar1.Value = e.ProgressPercentage;
45        }

46
47        void bgWorker_DoWork(object sender, DoWorkEventArgs e)
48ExpandedSubBlockStart.gifContractedSubBlock.gif        {
49            
50ExpandedSubBlockStart.gifContractedSubBlock.gif            /**//**//**//*执行耗时操作
51             * .
52             *. 
53             * .
54             * . 
55             */

56            
57            //报告进度
58            BackgroundWorker bgWorker = sender as BackgroundWorker;
59            for (int progress = 0; progress <= 100; progress++)
60ExpandedSubBlockStart.gifContractedSubBlock.gif            {
61                //当需要暂停操作时,阻止后台线程继续执行
62                while (isSuspend)
63ExpandedSubBlockStart.gifContractedSubBlock.gif                {
64                    Thread.Sleep(50);
65                }

66                
67                bgWorker.ReportProgress(progress);
68                Thread.Sleep(100);
69            }

70
71        }

72
73        private void btnSuspend_Click(object sender, EventArgs e)
74ExpandedSubBlockStart.gifContractedSubBlock.gif        {
75            if (isSuspend)
76ExpandedSubBlockStart.gifContractedSubBlock.gif            {
77                isSuspend = false;
78            }

79            else
80ExpandedSubBlockStart.gifContractedSubBlock.gif            {
81                isSuspend = true;
82            }

83        }

84    }

85}

 

          这种解决方案其实在BackgroundWorker中已经被应用,当需要请求取消挂起的后台操作时,需要调用BackgroundWorker的CancelAsync()方法。但是,该方法仅仅是将BackgroundWorker的属性CancellationPending属性设为true。位于DoWork()事件中的代码必须在适当的位置检查CancellationPending属性,如果为true,则退出当前程序。基于这个思路,将BackgroundWorker简单的封装一下:

 

ContractedBlock.gif ExpandedBlockStart.gif 简单封装
 1using System;
 2using System.Collections.Generic;
 3using System.Text;
 4using System.ComponentModel;
 5
 6namespace BackgroundWorkerDemo
 7ExpandedBlockStart.gifContractedBlock.gif{
 8    class BackgroundWorkerDemo : BackgroundWorker
 9ExpandedSubBlockStart.gifContractedSubBlock.gif    {
10        private bool _suspensionPending;
11
12ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
13        /// 获取一个值,指示应用程序是否已请求暂停后台操作。
14        /// </summary>

15        public bool SuspendPending
16ExpandedSubBlockStart.gifContractedSubBlock.gif        {
17ExpandedSubBlockStart.gifContractedSubBlock.gif            get return _suspensionPending; }
18        }

19
20        public BackgroundWorkerDemo()
21ExpandedSubBlockStart.gifContractedSubBlock.gif        {
22            _suspensionPending = false;
23        }

24
25ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
26        /// 请求暂停挂起的后台操作。
27        /// </summary>
28        /// <returns></returns>

29        public bool SuspendAsync()
30ExpandedSubBlockStart.gifContractedSubBlock.gif        {
31            _suspensionPending = true;
32        }

33    }

34}

 

          这样,当需要暂停后台线程时,直接调用SuspendAsync()方法,然后在适当的位置检查SuspensionPending属性,如果为true,则执行替代方案中的代码。

          本人对多线程编程了解不多,这篇随笔仅仅作为一篇开发日志,以方便以后查阅。如果各位有什么更好的解决方案还请不吝赐教。

转载于:https://www.cnblogs.com/zhangyz215/archive/2008/12/24/1361657.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值