none
Timer(System.Windows.Forms) 是否多线程 RRS feed

  • 问题

  • a、MessageBox对话框在点击之前,主线程就应该停止了,
    b、默认不在主线程中修改界面,会报错;

    如果以上正确,为什么出现以下问题 ,
    由timer显示的对话框,显示后 主线程停止了,但其到时间还会弹出对话框;在timer里修改界面不报错。
    1、timer 调用的内容和主线程什么关系?
    2、timer是不是多线程?timer是什么原理?
    3、会不会前一次timer没处理完,后一次timer开始工作?  //最重要
    4、System.Windows.Forms.Timer和其他timer各有什么?给个链接就行

    谢谢大大们

    2009年7月12日 10:23

答案

  • 你好!
         .NET提供了三种记时器:
         1,System.Timers.Timer:
         这个Timer是使用线程池中的线程去执行任务的,可以指定线程池中的某个线程去执行任务

         2,System.Threading.Timer:
         和1中的Timer类似也是使用线程池中的线程去执行任务的,但是不可以指定线程池中的某个线程去执行任务
        
     
         3,System.Windows.Forms.Timer:
         该Timer的特点是执行任务的线程是专属于任务相关窗口的。决不能用这个Timer执行时间太长(例如几分之一秒)的任务,否则会造成界面无响应
        
        
    周雪峰
    2009年7月13日 0:04
    版主
  • 不会~
    System.Windows.Forms.Timer用的是 windows message 机制  直接给窗体message  窗体本身的线程是唯一的 所以不会“前一次Tick没处理完,后一次Tick开始工作”、 但是如果你第一个tick 没有处理完  有可能会忽略你下一个tick


    另外注意下  如果你的窗体正在messagebox 和showModelDialog,  本窗体的县城可能是被终止的  后台不会运行

    答案900, 目标五颗星
    2009年7月13日 2:42
    版主
  • hi 搂住,您正好用了Messagebox来测试,如果您用大型计算(for循环10亿次)或让线程Sleep那么您就会发现是一个一个timer事件来顺序执行。所以问题应该出在Messagebox上。

        通过调试窗口的“调用堆栈”和“寄存器”来监视,当ontick事件中没有Messagebox时,只会有一个ontick堆栈。而且是按时间顺序一个接一个运行。

        而当ontick事件中有Messagebox时,则,调用堆栈一直增加,除非您点击“确定”,才会返回。我猜测这是windows的消息机制的体现。system.windows.forms.timer是通过往窗体上发WM_TIME。估计Messagebox并非真正意义上阻塞主窗口线程,当我追踪到底层时,发现Messagebox已通过SafeNativeMethods开始调用外部的COM了,很有可能在这交出了主窗口线程的控制权。从而使得第二个Messagebox得以触发。根据堆栈的观测,当对第二个Messagebox点确定时,会返回第二个ontick的堆栈。并且阻塞窗口线程。点击确定后,执行完毕又会回到第一个timer ontick事件的堆栈。最终执行完毕。

       当不用timer,而是直接在代码中用Messagebox,则会等待确定,看起来像是阻塞了线程,个人估计Messagebox没有阻塞主窗口线程,而是阻止了消息发送到主窗口线程,所以感觉上是阻塞线程。而Timer则是内核发送WM_TIME,不会被Messagebox阻止。
    • 已标记为答案 _Joey 2009年7月13日 7:57
    2009年7月13日 7:20

全部回复

  • 我不是大大···我是路过看看的新人

    1.你说的是timer 的Tick事件吗?那个就在主线程生成的窗体类对象内····算是同步的吧?似乎timer的话必须要在窗体中使用

    2.Windows 计时器是为单线程环境设计的吧,原理吗我也不清楚,下面参考一个大哥的···
    利用ManualResetEvent的Wait  ,等待指定的时间。然后再配合Semaphore和锁进行控制

    有人说原理是这样的
    System.Windows.Forms.Timer是应用于WinForm中的,它是通过Windows消息机制实现的,类似于VB或Delphi中的Timer控件,内部使用API  SetTimer实现的。它的主要缺点是计时不精确,而且必须有消息循环,Console  Application(控制台应用程序)无法使用。  

    3.其实试验的时候是的····但是为什么我也不知道了
    4.啥意思····


    这个问的我不知道怎么回答啊
    求高人解答啊

    2009年7月12日 16:12
  • 你好!
         .NET提供了三种记时器:
         1,System.Timers.Timer:
         这个Timer是使用线程池中的线程去执行任务的,可以指定线程池中的某个线程去执行任务

         2,System.Threading.Timer:
         和1中的Timer类似也是使用线程池中的线程去执行任务的,但是不可以指定线程池中的某个线程去执行任务
        
     
         3,System.Windows.Forms.Timer:
         该Timer的特点是执行任务的线程是专属于任务相关窗口的。决不能用这个Timer执行时间太长(例如几分之一秒)的任务,否则会造成界面无响应
        
        
    周雪峰
    2009年7月13日 0:04
    版主
  • 个人观点:

    1. System.Windows.Forms.Timer 就是主线程的一部分
    2. System.Windows.Forms.Timer 并非多线程。至于原理....CPU 的时钟吧....可能...
    3. 前一次未完成,会阻塞后一次的操作
    4. MSDN 的内容
    System.Timers.Timer: ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref12/html/T_System_Timers_Timer.htm
    System.threading.Timer: ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref12/html/T_System_Threading_Timer.htm
    2009年7月13日 1:35
  •   1.   Windows计时器  
            system.windows.forms.timer  
      特点:计时器是为单线程环境设计的,其中,UI   线程用于执行处理。Windows   计时器的精度限定为   55   毫秒。这些传统计时器要求用户代码有一个可用的   UI   消息泵,而且总是在同一个线程中操作,或者将调用封送到另一个线程。  
       
      2.   线程计时器  
            system.threading.timer  
      特点:使用   TimerCallback   委托指定希望   Timer   执行的方法。此方法不在创建计时器的线程中执行,而是在系统提供的线程池线程中执行。  
       
      3.   服务器计时器  
            system.timers.timer  
      基于服务器的计时器是为在多线程环境下与辅助线程一起使用而设计的。由于它们使用不同的体系结构,因此基于服务器的计时器可能比Windows   计时器精确得多。服务器计时器可以在线程之间移动来处理引发的事件。  


    3、会不会前一次timer没处理完,后一次timer开始工作?  //最重要
    • 已标记为答案 _Joey 2009年7月14日 5:40
    • 取消答案标记 _Joey 2009年7月14日 5:40
    2009年7月13日 1:56
  • 3会  3是2的简单封装     而且 一般3存在的 windows service 是mta 的 不会影响事件
    如果强制你的程序是sta 3和2可能会先产生事件 等当前县城空闲才运行handler
    答案900, 目标五颗星
    2009年7月13日 2:38
    版主
  • 3会  3是2的简单封装     而且 一般3存在的 windows service 是mta 的
    答案900, 目标五颗星

    不好意思写错地方了,System.Windows.Forms.Timer 会不会前一次Tick没处理完,后一次Tick开始工作?
    2009年7月13日 2:40
  • 不会~
    System.Windows.Forms.Timer用的是 windows message 机制  直接给窗体message  窗体本身的线程是唯一的 所以不会“前一次Tick没处理完,后一次Tick开始工作”、 但是如果你第一个tick 没有处理完  有可能会忽略你下一个tick


    另外注意下  如果你的窗体正在messagebox 和showModelDialog,  本窗体的县城可能是被终止的  后台不会运行

    答案900, 目标五颗星
    2009年7月13日 2:42
    版主
  • 您好,system.windows.forms.timer 的实现与其它两个Timer不同,不是基于多线程的设计,而是用WM_TIME来不断地发送消息。在system.windows.forms.timer中一个订阅的事件完成后才会执行下一个事件,故会阻塞下一个timer的事件。
    3个Timer的区别,可以参考《Programming .NET Components》的第8章第9节,里面有简单的介绍。
    2009年7月13日 3:15
  • 1、.NET有三种计时器,你所使用的应该是Windows计时器,对于Windows计时器,其响应代码应在窗体线程上执行(即timer调用的内容将在主线程上执行)。
    2、但是我觉得无论如何,计时和触发事件的操作都是单独的线程上执行的,也许每个计时器一个线程,也许多个计时器共用一个线程。
    3、由于响应代码需要在窗体线程上执行,因此,不可能出现多个响应操作同时执行的情况。
    4、关于另外两个计时器,请参考MSDN:System.Threading.Timer, System.Timers.Timer


    2009年7月13日 4:52
  • 不会~
    System.Windows.Forms.Timer用的是 windows message 机制  直接给窗体message  窗体本身的线程是唯一的 所以不会“前一次Tick没处理完,后一次Tick开始工作”、 但是如果你第一个tick 没有处理完  有可能会忽略你下一个tick


    另外注意下  如果你的窗体正在messagebox 和showModelDialog,  本窗体的县城可能是被终止的  后台不会运行

    答案900, 目标五颗星

    和实验结果 有些矛盾呢

    a、Messagebox弹出窗口时主线程被终止;
    b、on tick 内容在主线程执行;

    c、如果on tick内容包括弹出窗,在前一个弹出窗口没被处理前,仍会弹出窗口;

    ab 和 c 矛盾啊! 
    2009年7月13日 6:27
  • hi 搂住,您正好用了Messagebox来测试,如果您用大型计算(for循环10亿次)或让线程Sleep那么您就会发现是一个一个timer事件来顺序执行。所以问题应该出在Messagebox上。

        通过调试窗口的“调用堆栈”和“寄存器”来监视,当ontick事件中没有Messagebox时,只会有一个ontick堆栈。而且是按时间顺序一个接一个运行。

        而当ontick事件中有Messagebox时,则,调用堆栈一直增加,除非您点击“确定”,才会返回。我猜测这是windows的消息机制的体现。system.windows.forms.timer是通过往窗体上发WM_TIME。估计Messagebox并非真正意义上阻塞主窗口线程,当我追踪到底层时,发现Messagebox已通过SafeNativeMethods开始调用外部的COM了,很有可能在这交出了主窗口线程的控制权。从而使得第二个Messagebox得以触发。根据堆栈的观测,当对第二个Messagebox点确定时,会返回第二个ontick的堆栈。并且阻塞窗口线程。点击确定后,执行完毕又会回到第一个timer ontick事件的堆栈。最终执行完毕。

       当不用timer,而是直接在代码中用Messagebox,则会等待确定,看起来像是阻塞了线程,个人估计Messagebox没有阻塞主窗口线程,而是阻止了消息发送到主窗口线程,所以感觉上是阻塞线程。而Timer则是内核发送WM_TIME,不会被Messagebox阻止。
    • 已标记为答案 _Joey 2009年7月13日 7:57
    2009年7月13日 7:20
  • hi 搂住,您正好用了Messagebox来测试,如果您用大型计算(for循环10亿次)或让线程Sleep那么您就会发现是一个一个timer事件来顺序执行。所以问题应该出在Messagebox上。

        通过调试窗口的“调用堆栈”和“寄存器”来监视,当ontick事件中没有Messagebox时,只会有一个ontick堆栈。而且是按时间顺序一个接一个运行。

        而当ontick事件中有Messagebox时,则,调用堆栈一直增加,除非您点击“确定”,才会返回。我猜测这是windows的消息机制的体现。system.windows.forms.timer是通过往窗体上发WM_TIME。估计Messagebox并非真正意义上阻塞主窗口线程,当我追踪到底层时,发现Messagebox已通过SafeNativeMethods开始调用外部的COM了,很有可能在这交出了主窗口线程的控制权。从而使得第二个Messagebox得以触发。根据堆栈的观测,当对第二个Messagebox点确定时,会返回第二个ontick的堆栈。并且阻塞窗口线程。点击确定后,执行完毕又会回到第一个timer ontick事件的堆栈。最终执行完毕。

       当不用timer,而是直接在代码中用Messagebox,则会等待确定,看起来像是阻塞了线程,个人估计Messagebox没有阻塞主窗口线程,而是阻止了消息发送到主窗口线程,所以感觉上是阻塞线程。而Timer则是内核发送WM_TIME,不会被Messagebox阻止。

    早说过你很专业了嘛:)
    VC正在学
    2009年7月13日 7:57
  • To _Joey :
    哈,谢谢,也只是个人推理,不见得都对。
    • 已建议为答案 wefgod 2009年7月14日 6:27
    2009年7月13日 8:05
  • To _Joey :
    哈,谢谢,也只是个人推理,不见得都对。

    神人啊这位!太厉害了!
    2009年7月14日 6:27