在 C# 的构造函数中声明线程

Declaring Thread in a Constructor in C#

我目前正在研究线程以及如何使用它们。 与此同时,我正在研究我对 Events/Global 事件的理解(仅供参考)。

我在一个对象中定义了一个线程,该线程将在 thread.Start() 上使用该函数。

internal class Name
    {
        private Thread testthread;

        private EventWaitHandle globalEvent;

        private Eventstest evente = new Eventstest(); //Just to add some methods

        public Name(Thread testthread, EventWaitHandle globalEvent)
        {
            this.testthread = testthread;
            this.globalEvent = globalEvent;
        }

        
        public void Execute()
        {
            bool terminate = false;
            bool eventset = false;
            bool rdy = false;

            while (!terminate)
            {
                if (evente.CheckSysEvent(globalEvent)) 
                {
                    eventset = true; //This is just to check with debugger if the event was raised elsewhere
                }
                Thread.Sleep(100);
            }
        }
    }

所以现在,就像 Windows Forms 应用程序中的这个例子一样,我试图设置这个 class 的实例,同时设置线程的实例(与工作稍后应该 运行 方法)。 我在这里为这部分苦苦挣扎。

private void btn_runThread_Click(object sender, EventArgs e)
        {
            threadClass = new Name(new Thread(ProblemHere), globalEvent);
            threadClass.Execute();            
        }

这是一个启动线程的按钮,它应该完成它应该做的工作。 变量threadClass只是forms1.cs:

中的初始化
Name threadClass;

我知道它想要一个委托来传递线程在启动时应该使用的方法。 我尝试了几乎所有我发现的东西,但无法让它发挥作用。 我不能只传递方法,那是行不通的。 据我所知,我在 c# 文档中发现的内容几乎只是传递方法。 这可能是错误的。 我刚刚注意到,如果 property/thread.start 仅在 运行 时间创建,我如何才能真正调用它?

这不是一个完整的解决方案,但可以帮助您前进:

我的建议是像这样进行一点重构

internal class Name
{
    private Thread testthread;

    private EventWaitHandle globalEvent;

    private Eventstest evente = new Eventstest(); //Just to add some methods

    public Name(EventWaitHandle globalEvent)
    {
        this.testthread = new Thread(Execute); // Creates a Thread, that is directed to execute `Execute`
        this.globalEvent = globalEvent;
        this.testthread.Start();  // Tells the framework to schedule the thread for execution.
    }
    
    private void Execute()
    {
        bool terminate = false;
        bool eventset = false;
        bool rdy = false;

        while (!terminate)
        {
            if (evente.CheckSysEvent(globalEvent)) 
            {
                eventset = true; //This is just to check with debugger if the event was raised elsewhere
            }
            Thread.Sleep(100);
        }
    }
}

然后在按钮处理程序中执行

private void btn_runThread_Click(object sender, EventArgs e)
{
    threadClass = new Name(globalEvent);
}

请注意,仍然存在很大一部分错误和错误,但至少,这将保留您的 GUI 线程 运行,并且您可能会从这里获得理解并继续。


一种完全不同的方法(如果您愿意考虑的话)是使用 System.Windows.Forms.Timer 代替。这样你就可以有一个方法每 X 次调用一次,它会在你试图让线程执行时检查 globalevent 的状态。然而,计时器使这更方便。

典型的方法是在构造函数中创建线程,如 Fildor 的回答中所述。

但我想指出,直接使用 Thread 对象很少是正确的做事方式,因为还有其他工具更适合您尝试做的任何事情:

  • 如果您想在后台线程上执行一次计算量大的操作,并在完成后更新 UI。使用 Task.Run and async/await
  • 如果你想每隔 X 秒做一些事情。使用定时器。在主线程或后台线程上都有 运行 的计时器,请参阅 differences between timers
  • 如果您想 运行 并行计算繁重的操作,请使用 Parallel.For,可能与 Task.Run 结合使用。
  • 如果您想在不冻结 UI 的情况下调用 IO 密集型方法,请将 async/await 与适当的异步方法结合使用。
  • 如果您想创建 producer/consumer 或其他处理管道,可以使用 DataFlow