关于 C# 事件调用中使用的线程

2024-03-07

下面是我学习C#事件调用的代码,以及其中使用线程的情况。我在使用过程中有几个疑问:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace EventSample1
{
    public class MyTimerClass
    {
        public event EventHandler MyElapsed;
        //----
        private void OnOneSecond(object source, EventArgs args)
        {
            if (MyElapsed != null)
            {
                MyElapsed(source, args);
            }
        }
        //----
        private System.Timers.Timer MyPrivateTimer; 
        //----
        public MyTimerClass()
        {
            MyPrivateTimer = new System.Timers.Timer();
            MyPrivateTimer.Elapsed += OnOneSecond;
            //----
            MyPrivateTimer.Interval = 1000;             
            MyPrivateTimer.Enabled = true;
        }
     }
    //----
    class classA
    {
        public void TimerHandlerA(object source, EventArgs args)
        {
            Console.WriteLine("{0} class A handler called! at thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
        }
    }
    class classB
    {
        public static void TimerHandlerB(object source, EventArgs args)
        {
            Console.WriteLine("{0} class B handler called! at thread {1}", DateTime.Now, Thread.CurrentThread.ManagedThreadId);
        }
    }
    //----
    class Program
    {
        static void Main()
        {
            Console.WriteLine("Main thread on {0}", Thread.CurrentThread.ManagedThreadId);
            classA ca = new classA();
            MyTimerClass mc = new MyTimerClass();
            //----
            mc.MyElapsed += ca.TimerHandlerA;
            mc.MyElapsed += classB.TimerHandlerB;
            //----
            Thread.Sleep(2250);
        }
    }
}

the results is like this: enter image description here

这表明当mc.Elapsed被调用时,主线程打开另一个(invoke?)线程执行两个EventHandler(TimerEventHandlerA 和 B)。

我的问题1。就是它:

为什么主线程被标记为No.1,而新调用的线程被标记为No.4? 那么,2号线和3号线是什么? 他们在做什么?


然后我更改了 main() 中的代码,让主线程休眠时间从 2.25 秒变为 5.25 秒,

Thread.Sleep(5250);

我得到了不同的结果(另一个线程被调用 ):

我的问题2。就是它:

使用的线程数完全由系统决定吗?是人们所说的“线程池”来做到这一点吗?


之后,我在之前插入另一行Thread.Sleep()看看会发生什么?

//----
mc.MyElapsed += ca.TimerHandlerA;
mc.MyElapsed += classB.TimerHandlerB;
Console.ReadLine();
//----
Thread.Sleep(2250);

我这样做的原因是:

据我了解,当事件 myElapsed 被调用时,A 和 B 将被调用。在调用它们之前,程序将使用一个新线程来执行中的代码TimerEventHandlerA和B。主线程很快就会回到readline()排队等待我们输入。就像我们使用的时候一样Thread.Sleep(),主线程刚刚回到Thread.Sleep()并在2.25秒后关闭正在运行的程序!

But the result is NOT like what we think, the TimerEventHandler A and B just be called again and again......like the main thread will never come to readline()! enter image description here

我只是在同一个位置使用不同的线,为什么结果如此不同?

我想这可能涉及到线程中的一些细节,但是我的书并没有太多谈论C#中线程的使用,有人可以推荐另一本自学的好书吗?

提前致谢!


为什么主线程被标记为No.1,而新调用的线程被标记为No.4?那么,2号线和3号线是什么?他们在做什么?

不关心线程id。

  • 每个线程都有一个唯一的id
  • System.Timers.Timer https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx将在线程内调用计时器事件(可以是除主线程之外的任何线程)
  • System.Timers.Timer可以使用完成其工作所需的任意数量的线程

所以我们只能依赖事件将被调用并且调用线程将具有与主线程不同的id。

使用的线程数完全由系统决定吗?是人们所说的“线程池”来做到这一点吗?

是的,这取决于实施System.Timers.Timer如何调用计时器事件。我们确实不知道是否涉及线程池,但这真的很重要吗?只要实例的行为符合记录/预期,我就不关心实现。

如果我确实关心实施情况,我只需看看sources http://referencesource.microsoft.com/#System/services/timers/system/timers/Timer.cs#897683f27faba082看看幕后发生了什么。

...就像主线程永远不会出现一样Console.ReadLine()!

那么主线程肯定会到达那条线。但有什么作用Console.ReadLine()真的吗?

It is waiting for an input from then user and will continue when the user press ENTER. So until you press ENTER the main thread is blocked. But all other threads are still running and will call the events which will output some text to console.

为了证明这一点,我们只需添加一些行:

mc.MyElapsed += ca.TimerHandlerA;
mc.MyElapsed += classB.TimerHandlerB;

Console.WriteLine( "I am waiting for your input!" );
Console.ReadLine();
Console.WriteLine( "Thank you!" );

Thread.Sleep(2250);

Console.WriteLine( "Finished." );


Main thread on 1
I am waiting for your input!
2016-7-12 7:53:40 class A handler called! at thread 4
2016-7-12 7:53:40 class B handler called! at thread 4
2016-7-12 7:53:41 class A handler called! at thread 4
2016-7-12 7:53:41 class B handler called! at thread 4
  

and it will continue until you hit the ENTER key. And when you hit you should see the events are still called during the Thread.Sleep(2250).



2016-7-12 7:53:50 class A handler called! at thread 4
2016-7-12 7:53:50 class B handler called! at thread 4
Thank you!
2016-7-12 7:53:51 class A handler called! at thread 4
2016-7-12 7:53:51 class B handler called! at thread 4
2016-7-12 7:53:52 class A handler called! at thread 4
2016-7-12 7:53:52 class B handler called! at thread 4
Finished.
  

谁能推荐另一本自学的好书?

不,这类问题是无关 https://stackoverflow.com/help/on-topic这里就这样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于 C# 事件调用中使用的线程 的相关文章

随机推荐

  • 如何使这个 SwingWorker 代码可测试

    考虑这段代码 public void actionPerformed ActionEvent e setEnabled false new SwingWorker
  • 角度.net core api cors预检请求错误

    我无法使 cors 工作 Angular net core 2 1 我收到此错误 访问 XMLHttpRequest 位于 https dev SaveAPP https dev SaveAPP 从原点 https 页面 https pag
  • dc.js - 动态更改折线图中堆叠层的 valueAccessor 并重绘它

    我正在尝试实现一个仪表板来显示基本数据 我实际上完全陷入了一个问题 奇怪的是 我在网上找不到任何类似的东西 所以我没有太多关于如何继续前进的线索 我主要有两个图表 a lineChart called stackChart that 使用
  • 极端情况、意外和不寻常的 MATLAB [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 JavaFX 中重新加载应用程序?

    我有一个小游戏 里面有New Game按钮 有很多变量需要重置New Game按钮被按下 是否有任何方法可以轻松地重新加载整个应用程序或任何替代方案来刷新场景 阶段或变量 我只想在首次加载应用程序时将其带入初始阶段 我在互联网上浏览了不同的
  • PHP 按位异或 vs. JavaScript 按位异或

    我正在尝试找到一种方法来制作PHP Bitwise XOR结果与以下结果相符JavaScript Bitwise XOR 我遇到了这个问题的不同问题 但都没有答案 这里有几个 Javascript 和 PHP 异或等效项 https sta
  • ios 录制视频并同时播放音频

    我想同时录制视频和播放音频 当开始录制视频时 预加载的音频开始播放 当停止视频录制时 音频也停止播放 我尝试使用第三方库录制视频 迅捷相机 https github com Awalz SwiftyCam https github com
  • 纱线错误:没有场景;必须至少有一个

    我尝试安装Yarn https yarnpkg com lang en 当我使用yarn我得到的命令 00h00m00s 0 0 ERROR There are no scenarios must have at least one my
  • 对溢出菜单项使用自定义视图

    我在对操作栏 Sherlock 中的溢出菜单执行任何操作时遇到了真正的困难 理想情况下 我想使用自定义TextView为每个项目设置不同的字体并更改颜色pressed state 我已经尝试过 都没有成功 更改操作栏溢出的样式 https
  • 使用原始 JavaScript 提交函数时,jQuery 验证不会触发

    我的表单上有 jQuery 验证 当我单击提交按钮时 将调用 保存 函数 function save var form document getElementById myForm form submit lt jquery validat
  • 如何使用 SAM 在本地运行 C++ AWS Lambda 函数?

    我想尝试 AWS Lambda 的自定义 C 运行时并使用本地测试SAM https docs aws amazon com serverless application model latest developerguide what i
  • 如何使用 Pandas 对多索引列重新排序?

    表格显示在这里 https i stack imgur com Q4Hmo png code dff pd DataFrame Country France 4 China 4 Progress Develop Middle Operate
  • 光流 .flo 文件

    我有几个关于做光流项目的问题 我使用Python 2 计划使用烤宽面条使用深度学习来学习光流 并且不知道如何将c 函数转换为python的流可视化函数 我下载了 来自http vision middlebury edu flow data
  • 如何使用 Qt HTML5 应用程序向浏览器发送数据或从浏览器发送数据

    在线教程均未展示如何创建 Qt HTML5 应用程序 理想情况下 我只需要一种在 webkit 和 Qt 之间发送数据的方法 一个字符串即可 当我创建 Qt HTML5 应用程序时它会生成 myApp pro html5 applicati
  • 将结构数组从 C# 传递到 C++ DLL

    我试图将结构数组传递到 C DLL 中并遇到问题 我已经尝试了好几天了 但没有成功 我可以从 C 中获取数据 但当我尝试使用 NET 获取结构数组时 我遇到了问题 C 原型是 static declspec dllexport int So
  • 模板的丑陋编译器错误

    template
  • Java 文本格式化

    如何将文本字符串 如名字 姓氏 电话等 格式化为列 这不会做到这一点 String customer t surname t givenname t blablabla 请参阅文档String format http java sun co
  • 按名称按字母顺序排序在数据表中不起作用

    在这里 我从控制器中获取了数据 一切都很好 根据字母顺序 但在数据表中它不是我想要得到的 意味着查看时按字母顺序排列 这里所有数据默认按降序排列 aaSorting 0 desc 我需要它根据名称字段按字母顺序排序 我附上了一张快照以供更多
  • Parse SDK无法在后台获取位置,总是超时异常

    这是我正在使用的代码 ParseGeoPoint getCurrentLocationInBackground 10000 new LocationCallback Override public void done ParseGeoPoi
  • 关于 C# 事件调用中使用的线程

    下面是我学习C 事件调用的代码 以及其中使用线程的情况 我在使用过程中有几个疑问 using System using System Collections Generic using System Linq using System Te