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

C# 关于在C中调用事件时使用的线程#,c#,multithreading,C#,Multithreading,下面是我用来学习C#中事件调用的代码,以及其中使用的线程的情况。我在使用它时有几个问题: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace EventSample1 { public class MyTimerClass { public event EventHandler

下面是我用来学习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);
        }
    }
}
结果如下:

它显示当调用
mc.appeased
时,主线程打开另一个(invoke?)线程以执行两个EventHandler(
TimerEventHandler
A和B)

我的问题1。这是:

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


然后我更改了main()中的代码,让主线程从2.25s'休眠到5.25s'

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

我的问题2。这是:

正在使用的线程数完全由系统决定吗?这就是人们所说的“线程池”吗?


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

//----
mc.MyElapsed += ca.TimerHandlerA;
mc.MyElapsed += classB.TimerHandlerB;
Console.ReadLine();
//----
Thread.Sleep(2250);
我这样做的原因是:

据我所知,当事件被调用时,A和B将被调用。在调用它们之前,程序将使用一个新线程来执行
TimerEventHandler
a和B中的代码。主线程将很快返回
readline()
行,等待我们输入。就像我们使用
Thread.Sleep()
时一样,
主线程只需返回
Thread.Sleep()
并在2.25s'后关闭正在运行的程序

但是结果是,不像我们所想的那样,
TimerEventHandler
A和B只是一次又一次地被调用……就像主线程永远不会到达
readline()

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

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


提前谢谢

我同意其他评论,这个问题太宽泛了,不能简单回答。我建议你看看这个链接:它涵盖了很多细节,很可能有关于这个和许多其他问题的答案,这些问题都在你脑海中萦绕

总的来说,我认为你太担心引擎盖下发生的事情的确切细节了。是的,很好地理解了它们是如何联系在一起的,但对于分配给线程ID的实际值来说,这并不重要。系统将为您管理线程分配,并且由于每个线程的执行顺序和运行时间是不确定的,因此您将无法从ThreadID本身的值推断任何执行顺序。虽然我相信threadID=1始终是主线程,但我个人不会相信将来会一直是这样。 当您深入了解线程时,会发现使用锁定、锁存和信号量同步两个或多个线程的更重要方面。这是控制和/或跟踪执行顺序的正确方法,对于这些,了解ThreadID并不重要

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

  • 每个线程都有一个唯一的id
  • 将调用线程内部的计时器事件(它可以是除主线程之外的任何线程)
  • System.Timers.Timer
    可以使用执行其任务所需的任意多个线程
因此,我们只能依赖于事件将被调用,并且调用线程将具有与主线程不同的id

使用的线程数完全由系统决定吗?这就是人们所说的“线程池”吗? 是的,这取决于
System.Timers.Timer
如何调用计时器事件。我们不知道是否涉及线程池,但这真的很重要吗?只要实例的行为符合文档/预期,我就不关心实现

如果我真的关心实现的话,我只需要看一看引擎盖下面发生了什么

... 就像主线程永远不会出现在控制台上一样。ReadLine()
! 主线程肯定会到达那条线。但是
Console.ReadLine()
真正做什么呢

它正在等待用户的输入,并将在用户按ENTER键时继续。因此,在按ENTER键之前,主线程将被阻止。但所有其他线程仍在运行,并将调用将向控制台输出一些文本的事件

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

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." );
有人能推荐另一本自学的好书吗?
不,这类问题就在这里。

Read-这取决于调用事件的线程上下文所在的计时器本身。你只能依靠:a)它将被称为b)它不会在主线程上下文中被称为。如果你以三个独立的问题重新发布,你可能会得到这些问题的答案。现在有点太宽泛了。@Enigmativity谢谢你的建议!也许你可以先给出一两个你觉得舒服的答案?谢谢@SirRufo感谢您的回复!但首先,你能告诉我你回答了哪个问题吗?第一个?第二个?还是第三个?谢谢@phil blackburn,这个链接特别有用!真的,真的谢谢你@鲁福爵士,你的回答条理清晰,尤其是最后一个问题。。。。。。有关Console.ReadLine的详细信息对于解决我的问题非常重要。但是你在哪里找到这些?它们是否也来自msdn上的链接?(如您上面提供的链接?)-如果您不确定在哪里搜索,只需询问即可 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 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.