不返回值的 C# 字符串函数
本文关键字:字符串 函数 返回值 | 更新日期: 2023-09-27 18:35:06
我对这个函数有问题。
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();
这是方法中的事件处理程序,它与您的方法调用异步运行。不能期望在事件句柄中返回变量集。
将值存储在全局范围内的其他位置,或者使用例如回调操作来返回值
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);
};
}
MichaC的答案基本上有重复答案的风险,以下是我对你为什么观察这种行为的解释,可能有一个更简单的解决方案。
此代码
artnet.NewPacket += (object sender, ArtNet.Sockets.NewPacketEventArgs<ArtNet.Packets.ArtNetPacket> e) =>{
//code omitted
}
说的是"当artnet在未来的某个时候引发NewPacket事件时,执行{和}之间的代码。
因此,当第一次遇到此代码时,除了运行时记得在发生artnet.NewPacket
时返回并执行代码之外,实际上什么都不会发生。
所以考虑到这一点,当你执行artnetReceiver
时,事件的顺序或多或少是这样的
- 声明
dataout
没有值。 - 您告诉运行时在将来某个时间发生
artnet.NewPacket
时执行某些代码。顺便说一下,这段代码是匿名委托的形式,它基本上是一个没有返回值的独立 void 函数。 - 然后你返回
dataout
,这当然是空白的。 - 稍后,发生
artnet.NewPacket
事件,并执行委托,但至关重要的是,如果遇到定义委托的最后一个右大括号,运行时将跳出此委托方法,它不会再次继续执行步骤 3! 这是因为从运行时的角度来看,委托不是定义它的函数的一部分,因此它被视为一个完全独立的方法。
也许这会让它更清楚;让我们将事件处理程序委托移动到它自己的一个单独的方法中,在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
方法中移动这个东西。