C# WinForm多线程开发(二) ThreadPool 与 Timer

原文地址:点击打开链接

[摘要]本文介绍C#
WinForm多线程开发之ThreadPool 与 Timer,并提供详细的示例代码供参考。

本文接上文,继续探讨WinForm中的多线程问题,再次主要探讨threadpool 和timer。

一 、ThreadPool

线程池(ThreadPool)是一种相对较简单的方法,它适应于一些需要多个线程而又较短任务(如一些常处于阻塞状态的线程),它的缺点是对创建的线程不能加以控制,也不能设置其优先级。由于每个进程只有一个线程池,当然每个应用程序域也只有一个线程池(对线),所以你将发现 ThreadPool类的成员函数都为static!当你首次调用ThreadPool.QueueUserWorkItem、 ThreadPool.RegisterWaitForSingleObject等,便会创建线程池实例。下面我就线程池当中的两函数作一介绍:

public static bool QueueUserWorkItem( //调用成功则返回true
	    WaitCallback callBack,//要创建的线程调用的委托
	    object state //传递给委托的参数
	    )//它的另一个重载函数类似,只是委托不带参数而已

    此函数的作用是把要创建的线程排队到线程池,当线程池的可用线程数不为零时(线程池有创建线程数的限制,缺身值为25),便创建此线程,否则就排队到线程池等到它有可用的线程时才创建。

public static RegisteredWaitHandle RegisterWaitForSingleObject(
    WaitHandle waitObject,// 要注册的 WaitHandle
    WaitOrTimerCallback callBack,// 线程调用的委托
    object state,//传递给委托的参数
    int TimeOut,//超时,单位为毫秒,
    bool executeOnlyOnce //是否只执行一次
);
public delegate void WaitOrTimerCallback(
    object state,//也即传递给委托的参数
    bool timedOut//true表示由于超时调用,反之则因为waitObject
);

此函数的作用是创建一个等待线程,一旦调用此函数便创建此线程,在参数waitObject变为终止状态或所设定的时间TimeOut到了之前,它都处于 “阻塞”状态,值得注意的一点是此“阻塞”与Thread的WaitSleepJoin状态有很大的不同:当某Thread处于 WaitSleepJoin状态时CPU会定期的唤醒它以轮询更新状态信息,然后再次进入WaitSleepJoin状态,线程的切换可是很费资源的;而用此函数创建的线程则不同,在触发它运行之前,CPU不会切换到此线程,它既不占用CPU的时间又不浪费线程切换时间,但CPU又如何知道何时运行它?实际上线程池会生成一些辅助线程用来监视这些触发条件,一旦达到条件便启动相应的线程,当然这些辅助线程本身也占用时间,但是如果你需创建较多的等待线程时,使用线程池的优势就越加明显。

更详细内容demo:

namespace TestMethodInvoker
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            //ThreadPool.RegisterWaitForSingleObject(
            //    ev,
            //    new WaitOrTimerCallback(WaitThreadFunc),
            //    4,
            //    2000,
            //    false//表示每次完成等待操作后都重置计时器,直到注销等待
            //    );
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadFunc), "test1");
            //Thread.Sleep(10000);
        }
        private delegate void MyInvokeDelegate(string name);
        private void Test(object o)
        {
            richTextBox1.Text += string.Format("the object is {0} \n", o);
        }
        public  void ThreadFunc(object b)
        {
            this.Invoke(new MyInvokeDelegate(Test), b);
        }
        public void WaitThreadFunc(object b, bool t)
        {
            richTextBox1.Text += string.Format("the object is {0},t is {1}\n", b, t);
        }
    }
}

     一个很值得扩展的地方时,这里的invoke 用的是代理,其实还有其他的方法,比如 action 和func。实例代码如下:

this.Invoke(new Action<string>(this.ChangeText), o.ToString());
this.Invoke(new Action(delegate() { this.textBox1.Text = o.ToString();}));
private void DoSomething(object o)
{
    System.Func<string, int> f = new Func<string, int>(this.GetId);
    object result = this.Invoke(f, o.ToString());
    MessageBox.Show(result.ToString());
}
private int GetId(string name)
{
    this.textBox1.Text = name;
    if (name == "Y")
    {
       return 999;
    }
    else
    {
        return 0;
    }
}

二、 Timer

它适用于需周期性调用的方法,它不在创建计时器的线程中运行,它在由系统自动分配的单独线程中运行。这和Win32中的SetTimer方法类似。它的构造为:

public Timer(
    TimerCallback callback,//所需调用的方法
    object state,//传递给callback的参数
    int dueTime,//多久后开始调用callback
    int period//调用此方法的时间间隔
);//

如果 dueTime 为0,则 callback 立即执行它的首次调用。如果 dueTime 为 Infinite,则 callback 不调用它的方法。计时器被禁用,但使用 Change 方法可以重新启用它。如果 period 为0或 Infinite,并且 dueTime 不为 Infinite,则 callback 调用它的方法一次。计时器的定期行为被禁用,但使用 Change 方法可以重新启用它。如果 period 为零 (0) 或 Infinite,并且 dueTime 不为 Infinite,则
callback 调用它的方法一次。计时器的定期行为被禁用,但使用 Change 方法可以重新启用它。 

在创建计时器之后若想改变它的period和dueTime,我们可以通过调用Timer的Change方法来改变:

public bool Change(
    int dueTime,
    int period
);//

    显然所改变的两个参数对应于Timer中的两参数。

时间: 2024-09-09 04:51:23

C# WinForm多线程开发(二) ThreadPool 与 Timer的相关文章

C# WinForm多线程开发(一) Thread类库

原文地址:点击打开链接 [摘要]本文介绍C# WinForm多线程开发之Thread类库,并提供简单的示例代码供参考. Windows是一个多任务的系统,如果你使用的是windows 2000及其以上版本,你可以通过任务管理器查看当前系统运行的程序和进程.什么是进程呢?当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的,线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针.程序计数器等),但代码区是共享的,即不

C# WinForm多线程开发(三) Control.Invoke

原文地址:点击打开链接 [摘要]本文介绍C# WinForm多线程开发之Control.Invoke,并提供详细的示例代码供参考. 下面我们就把在Windows Form软件中使用Invoke时的多线程要注意的问题给大家做一个介绍. 首先,什么样的操作需要考虑使用多线程?总的一条就是,负责与用户交互的线程(以下简称为UI线程)应该保持顺畅,当UI线程调用的API可能引起阻塞时间超过30毫秒时(比如访问CD-ROM等速度超慢的外设.进行远程调用等等)就应该考虑使用多线程.为什么是30毫秒?30毫秒

请问谁有C# WINFORM结合BarTender二次开发的源码或案例。

问题描述 请问谁有C#WINFORM结合BarTender二次开发的源码或案例,给一个下载的谢谢. 解决方案 解决方案二:如题..需要WINFORM引用BarTender的编辑器的源码.谢谢解决方案三:7w底价,其余费用甲方负责,我帮你弄,2个月交付解决方案四:引用2楼conmajia的回复: 7w底价,其余费用甲方负责,我帮你弄,2个月交付 ......不是吧,我只是想把BarTender的编辑器引用支WINFORM中..做一个小编辑软件..我自己都不收钱的.

iOS多线程开发系列之(二)NSOperation

上一篇我们简单的对iOS多线程开发系列(一)三种多线程办法进行对比性能和操作的复杂度,并认真介绍了NSThread的使用. 我们借助上一次的例子完全可以采取NSOperation方法进行实现 NSOperation不具备封装操作的能力,必须使用它的子类: NSInvocationOperation NSBlockOperation 更简洁的Block实现方法,功能上与 NSInvocationOperation基本一致 自定义子类继承NSOperation,实现内部相应的方法 NSInvocat

iOS多线程开发之深入GCD

iOS多线程开发之深入GCD 一.前言         在以前的一些系列博客中,对iOS中线程的管理做了总结,其中涵盖了GCD的相关基础知识:http://my.oschina.net/u/2340880/blog/417746.那里面将GCD的线程管理能力,列队组能力,通过信号和消息控制程序流程的能力都有介绍,这里,我们继续深入GCD的功能,通过GCD来处理一些逻辑更加复杂的代码功能. 二.延时追加任务         当我们在程序中处理延时任务的时候,我们一般会通过两种方式,一种是通过定时器

c# winform 多线程使用的问题 多线登录new新窗体的时候 报错

问题描述 c# winform 多线程使用的问题 多线登录new新窗体的时候 报错 c# winform 多线程使用的问题 多线登录new新窗体的时候 Thread Thr=new Thread(new ThreadStart(test1)) Thr.Start(); public void test1() { form1 for=new form1(); for.show(); } 报 线程间操作无效: 从不是创建控件"lts"的线程访问它.如何解决呢 解决方案 up 习惯用委托去解

实际工作中,什么场景会用到多线程开发?

问题描述 工作1年了,没接触过多线程,有的说法现在 多核处理器比较普及了,多线程开发以后会越来越多.平时能接触到多线程开发的朋友,能说说什么时候能用到多线程么?举些例子吧!!我接触的代码都是 web层--> service层 -->dao --> sql.没见过多线程.. 问题补充:redstarofsleep 写道 解决方案 1. 网络蚂蚁,最典型的多线程就用,多个连接同时下载2. Web爬虫就用3. GUI程序中的异步响应,比如,你点击一个按钮,要求不会阻塞,可以起一个线程,让那个线

我使用C#winform 多线程自动定时弹出新窗体,但是窗体一直忙

问题描述 我使用C#winform多线程自动定时弹出新窗体,但是窗体一直忙.我比如定时5秒钟弹出一个新窗体,但是一直都是忙的状态,我无法对新窗体操作,即使改为1分钟弹一次也没有办法,怎么办? 解决方案 解决方案二:面对这样的提问方式,我只能回答:凉拌解决方案三:如果线程不是UI主线程的话,操作窗体需要用委托调用的,你可以用异步委托,到时间就弹出一个窗体解决方案四:代码如下Form1frm;privatevoidbutton1_Click(objectsender,EventArgse){vart

C#winform多线程问题,求救

问题描述 C#winform多线程问题,求救 C#winform多线程,有6000条数据,分别根据ID查询,把信息导出excel,开100个线程同时查询,线程没走完就导出了,就没有那么多条数据,怎么办?求救CountdownEvent handler = new CountdownEvent(100); for (int i = 0; i < 100; i++) { Thread Thd = new Thread(() => { DateTime staTime = DateTime.Now;