简体   繁体   English

在C#中正确处理事件

[英]Correct Event handling in C#

this is basically a follow up to a previous question ( Triggering an event in c# from c++ and declaring LPCWSTR ). 这基本上是对上一个问题( 从c ++在c#中触发事件并声明LPCWSTR )的后续操作。 I've revised my code based on the answers and comments I have received and I solved the initial issue, which was passing the event to the GpioSetupInterruptPin from a gpio api. 我已经根据收到的答案和评论修改了我的代码,并解决了最初的问题,该问题将事件从gpio api传递到GpioSetupInterruptPin I don't have a lot of documentation on the api but what i'm trying to achieve is: have a form with a white label; 我在api上没有很多文档,但是我想要达到的目的是:带有白色标签的表单; after pressing a switch, the label turns yellow. 按下开关后,标签变为黄色。 The problem i'm having now is the event seems to trigger as soon as it's created (the "execute" message is passed to the debug dialog and the label turns yellow) but it doesn't do anything when i toggle the switch. 我现在遇到的问题是事件似乎在创建事件后立即触发(“执行”消息传递到调试对话框,并且标签变为黄色),但是当我切换开关时它什么也没做。 I was told in the last question to use WaitForSingleObject but i'm not really sure where to call it and this article only added to my confusion. 在最后一个问题中,有人告诉我使用WaitForSingleObject,但我不确定在哪里调用它,而这篇文章只会使我感到困惑。

public partial class Form1 : Form
{
    // P/Invoke CreateEvent and WaitForSingleObject
    private void GPIO_Open() //get handle for gpio
    private void GPIO_Output() //output pin declaration

    private void button1_Click(object sender, EventArgs e)
    {
        Interrupt_Setup();
    }

    private void Interrupt_Setup()
    {
        hGPIO = GPIOapi.GpioOpenHandle(); //returns a handle to the gpio
        GIPO_ON = true;
        Debug.WriteLine("Driver open \n" + hGPIO);
        GPIO_Output(); //set output pins
        GPIO_Interrupt(Trigger); //configure interrupt
    }

    private void GPIO_Interrupt(string trigger)
    {
        bool ok;
        _Main();
        //INTERRUPT DECALRATION
        ok = GPIOapi.GpioSetupInterruptPin(hGPIO, port6, 4, GPIOapi.INT_TRIGGER_MODE.TRIGGER_MODE_EDGE,
            GPIOapi.INT_TRIGGER_POLARITY.TRIGGER_POL_HIGH_RISING, trigger, true);
        Thread waitThread=new Thread(WaitForTrigger);
        waitThread.Start();
        if (!ok)
            Debug.WriteLine("NO interrupt");
        else
            Debug.WriteLine("Interrupt set for:" + port6 + "04" + " at " + hGPIO);
    }

    public static string Trigger = "InputProcessUpdateHandler";
    public static IntPtr handle = CreateEvent(IntPtr.Zero, false, false, Trigger); //used P/Invoke 
    private static InputProcessor inputProcessor = null;

    public Color[] color =
    {
        Color.Orchid, Color.DarkOrchid, Color.GreenYellow, Color.CornflowerBlue, Color.SteelBlue,Color.Crimson
    };

    public int i = 0;

    public void WaitForTrigger()
    {
        while(true)
        {try
        {
            if (WaitForSingleObject(handle, 0xFFFFFFFF) == false)
            {
                BeginInvoke(((System.Action)(() =>label2.BackColor = color[i])));
                i++;
                if (i > 4)
                    i = 0;
            }
            Thread.Sleep(300);
        }
        catch (Exception e)
        { Debug.WriteLine("exception: " + e); }}
        }
    }

    private void _Main()
    {
        inputProcessor = new InputProcessor();
        ShowToggle showToggle = new ShowToggle(inputProcessor);
        inputProcessor.Process(label1);
    }

    public class ShowToggle
    {
        private InputProcessor _inputProcessor = null;

        public ShowToggle(InputProcessor inputProcessor)
        {
            _inputProcessor = inputProcessor;
            _inputProcessor.updateHandledBy += InputProcessUpdateHandler;
        }

        private void InputProcessUpdateHandler(Label label)
        {
            label.BackColor = Color.Yellow;
            Debug.Write("execute");
        }
   }

   public class InputProcessor
   {
       public delegate void InputProcessUpdateHandler(Label label);
       public event InputProcessUpdateHandler updateHandledBy = null;

       public void Process(Label label)
      {
          if (updateHandledBy != null)
            updateHandledBy(label);
      }
   }

If anyone could help me with this, I would be very grateful. 如果有人可以帮助我,我将非常感激。

*** I got it working but it looks a right mess. ***我让它工作了,但看起来一团糟。 Could anyone help me straighten it out? 有人可以帮我弄清楚吗?

You code is really confusing to me. 您的代码确实让我感到困惑。 I think what you want is something like this. 我认为您想要的是这样的东西。 Bear in mind I'm typing this into the SO text editor, so don't expect it to compile and just work - it's a guide. 请记住,我在SO文本编辑器中输入了此内容,因此不要指望它可以编译并可以正常工作-这只是一个指南。 Consider it a step above pseudocode. 认为它比伪代码高出一步。

public class DeviceInterrupt
{
    IntPtr m_gpio;
    string m_eventName;

    public event EventHandler OnInterrupt;

    public DeviceInterrupt(int port)
    {
        // get a driver handle
        m_gpio = GPIO_Open();

        // generate some unique event name
        m_eventName = "GPIO_evt_" + port;

        // wire up the interrupt
        GpioSetupInterruptPin(m_gpio, port, m_eventName, ...);

        // start a listener
        new Thread(EventListenerProc)
        {
            IsBackground = true,
            Name = "gpio listener"
        }
        .Start();
    }

    public void Dispose()
    {
        // TODO: release the handle
    }

    private void EventListenerProc()
    {
        // create the event with the name we sent to the driver
        var wh = new WaitHandle(false, m_eventName);

        while (true)
        {
            // wait for it to get set by the driver
            if (wh.WaitOne(1000))
            {
                // we have an interrupt
                OnInterrupt.Fire(this, EventArgs.Empty);
            }
        }
    }
}

Usage would then be something like this: 用法将是这样的:

var intr = new DeviceInterrupt(4);
intr.OnInterrupt += MyHandler;
....
void MyHandler(object sender, EventArgs a)
{
    Debug.WriteLine("Interrupt occurred!");
}

Note 注意

The Compact Framework doesn't support actual named system events, so the named WaitHandle I use in my code above is not a CF-supplied WaitHandle . Compact Framework不支持实际的命名系统事件,因此我在我的代码中使用的命名WaitHandle 不是 CF提供的WaitHandle Instead I'm using the one from the Smart Device Framework . 相反,我使用的是Smart Device Framework中的那个。 You could also P/Invoke to CreateEvent and WaitForSingleObject yourself. 您也可以自己P /调用CreateEventWaitForSingleObject

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM