C#字符串函数没有返回值

时间:2016-02-17 00:25:00

标签: c#

我对此功能有疑问。

public static string artnetReceiver()
{
    string dataout;
    List<string> dmxString = new List<string>();
    byte[] _dmxData = new byte[511];

    artnet.NewPacket += (object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e) =>
    {
        if (e.Packet.OpCode == ArtNet.Enums.ArtNetOpCodes.Dmx)
        {
            var packet = e.Packet as ArtNet.Packets.ArtNetDmxPacket;
            Console.Clear();

            if (packet.DmxData != _dmxData)
            {
                for (var i = 0; i < packet.DmxData.Length; i++)
                {
                    if (packet.DmxData[i] != 0)
                    {
                    }

                    int temp = i + 1;
                    string chanNum = temp.ToString();
                    string chanValue = packet.DmxData[i].ToString();

                    dmxString.Add(chanNum + "-" + chanValue);
                };

                //dmx stuff

                dataout = string.Join(",", dmxString.ToArray());
                dmxOut = dataout;
                //Console.WriteLine(dataout);//works here

                _dmxData = packet.DmxData;
            }
        }
    };
    return dataout; // doesn't work
}

无论出于何种原因,我构建的字符串都不会到达返回部分,但是当我在函数中使用Console.WriteLine(dataout);时,它会向控制台吐出,但如果我通过函数调用它,那么就像例如,Console.WriteLine(artnetReceiver());我得到一个空白的结果。 编辑新代码

public static void artnetReceiver()
        {  
               artnet.NewPacket += OnArtNet_NewPacket;  
        }

       public static string ProcessDataOut(string dataout)
       {
            return dataout;
       }

        /*public static void getDMXPackets()
        {
            artnetReceiver((val) =>
            {
                return val;
            });

        }*/

        public static void OnArtNet_NewPacket(object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e)
        {
            byte[] _dmxData = new byte[511];
            List<string> dmxString = new List<string>();
            string dataout; //included here so the sample will compile
            if (e.Packet.OpCode == ArtNet.Enums.ArtNetOpCodes.Dmx)
            {
                var packet = e.Packet as ArtNet.Packets.ArtNetDmxPacket;
                Console.Clear();

                if (packet.DmxData != _dmxData)
                {
                    for (var i = 0; i < packet.DmxData.Length; i++)
                    {
                        if (packet.DmxData[i] != 0)
                        {
                        }

                        int temp = i + 1;
                        string chanNum = temp.ToString();
                        string chanValue = packet.DmxData[i].ToString();

                        dmxString.Add(chanNum + "-" + chanValue);
                    };

                    //dmx stuff

                    dataout = string.Join(",", dmxString.ToArray());
                    dmxOut = dataout;
                    _dmxData = packet.DmxData;
                    ProcessDataOut(dataout);
                }
            }
        }


        byte[] _dmxData = new byte[511];

好吧我现在苦苦挣扎的问题实际上是后来在我的代码中调用例如artnetReceiver()并且当它运行时它返回字符串值以便我可以导出将其作为数据包字符串发送所以mstrResponse = "Data: " + artnetReceiver();

2 个答案:

答案 0 :(得分:3)

这是您的方法中的事件处理程序,它与您的方法调用异步运行。 您不能指望在事件句柄中返回变量集。

将值存储在全局范围内的其他位置,或者使用例如回调Action为您返回值

Action<T>

的使用示例
public static void AnotherFunction()
{
    ArtnetReceiver((val) =>
    {
        // do work with the value returned
    });
}

public static void ArtnetReceiver(Action<string> callback)
{
    artnet.NewPacket += (object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e) =>
    {
        // some stuff going on...

        var dataout = value;
        callback(dataout);
    };
}

答案 1 :(得分:1)

存在基本上对MichaC的答案有重复答案的风险,这里是我对你为什么观察这种行为的解释,并提供了一个可能更简单的解决方案。

此代码

artnet.NewPacket += (object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e) =>{
 //code omitted
}

说“当artnet在将来的某个时刻引发NewPacket事件时,执行{和}之间的代码。”

首先遇到此代码时,实际上没有任何事情发生,除了运行时记得在artnet.NewPacket发生时回来并执行代码。

因此,考虑到这一点,当您执行artnetReceiver时,事件的顺序或多或少都是

  1. 您声明dataout没有任何价值。
  2. 您告诉运行时在将来某个时间发生artnet.NewPacket时执行某些代码。顺便提一下,这段代码是匿名委托的形式,它基本上是一个没有返回值的自包含void函数。
  3. 然后返回dataout,这当然是空白的。
  4. 稍后,artnet.NewPacket事件发生,并且委托被执行,但关键的是,w hen遇到了定义委托的最后一个右括号,运行时跳出了这个委托方法,它没有继续执行第3步!这是因为从运行时的角度来看,委托不是定义它的函数的一部分,所以它被视为一个完全独立的方法。
  5. 也许这会使它更清晰;让我们将事件处理程序委托移动到它自己的单独方法中,在artnetReceiver之外定义:

    public static string artnetReceiver()
    {
        string dataout;
        List<string> dmxString = new List<string>();
        byte[] _dmxData = new byte[511];
        artnet.NewPacket += OnArtNet_NewPacket;
        return dataout; // doesn't work
    }
    

    事件处理程序是

    //note the return type - it's void!
    public void OnArtNet_NewPacket(object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e)
    {
    string dataout; //included here so the sample will compile
    if (e.Packet.OpCode == ArtNet.Enums.ArtNetOpCodes.Dmx)
            {
                var packet = e.Packet as ArtNet.Packets.ArtNetDmxPacket;
                Console.Clear();
    
                if (packet.DmxData != _dmxData)
                {
                    for (var i = 0; i < packet.DmxData.Length; i++)
                    {
                        if (packet.DmxData[i] != 0)
                        {
                        }
    
                        int temp = i + 1;
                        string chanNum = temp.ToString();
                        string chanValue = packet.DmxData[i].ToString();
    
                        dmxString.Add(chanNum + "-" + chanValue);
                    };
    
                    //dmx stuff
    
                    dataout = string.Join(",", dmxString.ToArray());
                    dmxOut = dataout;
                    //Console.WriteLine(dataout);//works here
    
                    _dmxData = packet.DmxData;
                }
            }
    }
    

    因此,您可以清楚地看到,当您将事件处理程序分配给事件时,实际上没有执行任何操作,只有在偶然触发代码执行时才会执行。

    因此,就解决方案而言 - 无论您需要对dataout执行什么操作,都必须从事件处理程序内部启动。最简单的方法是,如果您可以封装流程的下一步与artnetReceiver所在的同一类中包含的方法中的任何内容 - 假设您将其称为ProcessDataOut(string dataout)。 然后你只需修改事件处理程序,以便它最后调用该方法,传递dataout

    _dmxData = packet.DmxData;
    ProcessDataOut(dataout);
    }
    
      

    注意:ProcessDataOut方法不能有返回类型(嗯,它可以   但这没有意义,因为没有任何东西可以接受   返回值)。因此,无论您需要如何处理数据输出,都可以   需要在ProcessDataOut方法中执行此操作。这就是方法   异步/事件驱动代码有效:)

    然而,更优雅(也更灵活)的解决方案是使用MichaC的答案中指出的回调委托(Action或Func),但同样的概念适用;这个代表不能返回任何内容,并且必须执行您尝试实施的任何流程的“下一步”。

    这样做的含义是您可能需要反转您的应用程序逻辑;也就是说,而不是在“外部”等待artnetReceiver返回某些东西(它永远不会)的东西,而不是在内移动内的东西 artnetReceiver的ProcessDataOut方法