【问题标题】:How to end an interrupting thread in C#如何在 C# 中结束中断线程
【发布时间】:2012-12-08 12:12:07
【问题描述】:

我正在使用 Netduino 板,但在结束 NativeEventHandler(button) 时遇到问题。问题是主线程卡在 join() 函数上。我不明白为什么子线程运行后没有释放。

public class Program
{
    private static Thread mainThread;
    private static Thread childThread;     

    private static InterruptPort button = new InterruptPort(Pins.GPIO_PIN_D1, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelHigh);

    private static OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);

    public static void Main()
    {            
        mainThread = Thread.CurrentThread;
        Thread.Sleep(1000);
        while (true)
        {
            Thread.Sleep(100);
            button.OnInterrupt += new NativeEventHandler(ButtonEvent);
            mainThread.Suspend();
            childThread.Join();//It stuck here.
            Thread.Sleep(100);
            button.EnableInterrupt();
            button.ClearInterrupt();  
        }
    }

    private static void ButtonEvent(uint port, uint state, DateTime time)
    {
        childThread = Thread.CurrentThread;
        button.DisableInterrupt();          
        mainThread.Resume();
       // Thread.CurrentThread.Abort(); this .Abort() seems doesn't terminate the thread either.
    }
}

【问题讨论】:

  • 我认为加入是不必要的。子线程正在恢复主线程然后退出。无论如何都应该完成子线程。连接时子线程的状态是什么(参见调试线程窗口)?
  • 顺便说一句:msdn.microsoft.com/en-us/library/… 见备注部分的注意事项。这并不是执行同步的好方法。此外,您在循环的每次迭代中都订阅了 OnInterrupt 事件。这会导致问题。
  • 顺便说一句,为什么所有线程都放在首位?
  • @Pete 感谢您的回复。我现在使用 AutoResetEvent 而不是suspend() 和resume()。另一件事我不应该在循环的每次迭代中订阅 OnInterrupt,但我认为新的 NativeEventHandler(ButtonEvent) 对象应该在每次完成时从内存中释放,所以任何时候都只会有一个实例,不是吗是吗?
  • @Pete 我真的不懂面向对象,我是一名 C 程序员。这就是为什么当谈到 OO 时,我迷路了。那么“首先是线程的东西”是什么意思?我该如何改变呢?

标签: c# multithreading netduino


【解决方案1】:

首先,当您订阅某个活动时,您会一直保持订阅状态,直到您取消订阅。所以你只需要订阅一次。

我相信你可以像这样做netduino...

public class Program
{
    private static InterruptPort button = new InterruptPort(Pins.GPIO_PIN_D1, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLevelHigh);

    private static OutputPort led = new OutputPort(Pins.ONBOARD_LED, false);

    public static void Main()
    {            
        button.OnInterrupt += new NativeEventHandler(ButtonEvent);
        Thread.Sleep(Timeout.Infinite);
    }

    private static void ButtonEvent(uint port, uint state, DateTime time)
    {
        ... do whatever here ...
    }
}

所以基本上,无论你想在按下按钮时发生什么,都可以在 ButtonEvent 中执行

我认为你不需要做任何其他事情。

Thread.Sleep(Timeout.Infinite);

仅用于保持程序运行。

所以在...在这里做任何事情...你可以闪烁你的 LED 或任何你想做的事情。

【讨论】:

  • 非常感谢,这真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-16
  • 1970-01-01
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多