Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为查看数组而创建的索引器不';看不到对数组所做的更改_C#_Arrays_Properties_Indexer - Fatal编程技术网

C# 为查看数组而创建的索引器不';看不到对数组所做的更改

C# 为查看数组而创建的索引器不';看不到对数组所做的更改,c#,arrays,properties,indexer,C#,Arrays,Properties,Indexer,我对c#非常陌生,我正在为我设计的一块板创建一个串行端口类。其中此类包含打开/关闭连接到板的串行端口的方法。它还应该读取来自电路板的消息,并将来自UI的消息写入电路板(我正在使用表单应用程序输入和显示值) 我读取内部输入缓冲区并将字节放入我自己的软件缓冲区,当消息完成时,这将提示表单分析消息 为此,我创建了一个索引器来指向数组(来自表单)并获取它所需的字节 uint[] serialPortReceiveBuffer = new uint[3]; public delegate

我对c#非常陌生,我正在为我设计的一块板创建一个串行端口类。其中此类包含打开/关闭连接到板的串行端口的方法。它还应该读取来自电路板的消息,并将来自UI的消息写入电路板(我正在使用表单应用程序输入和显示值)

我读取内部输入缓冲区并将字节放入我自己的软件缓冲区,当消息完成时,这将提示表单分析消息

为此,我创建了一个索引器来指向数组(来自表单)并获取它所需的字节

    uint[] serialPortReceiveBuffer = new uint[3];
    public delegate void Del();
    Del promptFormAction = Form1.MsgReceived;

    public void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {   
        for (int i = 0; i <= 2; i++) 
        {
            serialPortReceiveBuffer[i] = (uint)serialPort1.ReadByte();
        }

        promptFormAction();  
    }

    public uint this[uint i]
    {
        get { return serialPortReceiveBuffer[i]; }
    }
我的问题是,当我使用索引器访问
serialPortReceiveBuffer
时,它看不到我在将接收到的字节放入同一数组时对其所做的更改。例如,当我收到我自己的协议-->“?10”的字符串时,缓冲区将填充[63][49][48]

虽然当我尝试使用索引器访问此缓冲区时,我得到[0][0][0]

请问有人能帮忙吗?另外,我知道可能还有其他一些事情我可以做得更好,所以如果你有任何一般性的建议,那就太好了。也用我能理解的语言。我刚刚开始关注很多C方面的问题,过去一年我一直在做嵌入式软件,但我不认为我自己是一个称职的程序员。
感谢您

通过您的代码,我不太确定您在表单中使用的
PCB
对象是否就是接收数据的对象。很可能您正在使用两个不同的实例,尤其是当您创建
Form1
的新实例时,无论何时数据进入

(编辑:从您对问题的评论可以清楚地看出,这正是问题所在。请按照以下说明接近您想要的内容)

我建议您重新设计代码,将收到的消息作为事件传递给现有的表单实例,而不是现在的方式。您可能遇到的另一个问题是,由于
DataReceived
事件是异步的,因此您认为获得的数据将被传入的下一条消息覆盖

我将声明一个表单实例可以订阅的事件,并将要分析的数据传递到事件中:

 public class MessageReceivedEventArgs: EventArgs
 {
     public MessageReceivedEventArgs(byte[] data) : base()
     {
         Data = data;
     }

     public byte[] Data
     {
         get;
         private set;
     }
}

public event EventHandler<MessageReceivedEventArgs> MessageReceived;
另外,我会将
serialPortReceiveBuffer
完全私有于该类,正如我所说的,如果不这样做,您可能会遇到同步问题。这就是为什么我在将数组传递给事件之前复制它

此更改允许任何订阅者在您意识到新数据进入时注册通知

要使用它,
Form1
应该如下所示(大致)


关于如何处理串行数据的另一条建议:您需要决定是从循环中的串行端口读取数据,还是依赖
DataReceived
事件。将循环放入事件中不是一个好主意,因为当您等待时,可能会在再次到达数据时调用事件


您需要做的是创建一个缓冲区,从可用的串行端口获取所有信息。如果你没有足够的数据,不要等待。相反,每当调用
DataReceived
时,将其添加到缓冲区,并在存在足够数据时处理消息。

我认为Thorsten的回答很好,按照这些思路重新设计它会很有意义,但作为绝对最低要求,如果希望为每个接收到的消息创建一个新的
Form1
实例,则需要将
pcbSerialPort
的实例传递给
MessageReceived
,然后传递给
Form1
类的构造函数。比如:

Action<pcbSerialPort> promptFormAction = Form1.MsgReceived;

public void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{   
    // as Thorsten noted, you need to rethink this loop anyway
    // what if there aren't at least three bytes to read?
    for (int i = 0; i <= 2; i++) 
    {
        serialPortReceiveBuffer[i] = (uint)serialPort1.ReadByte();
    }

    promptFormAction(this);  
}
您可以为
表单1
创建构造函数:

public Form1(pcbSerialPort pcb)
{
    PCB = pcb;
}

哪里定义了
PCB
?你确定你在看同一个实例吗?您确定已触发
datareceived
事件吗?IIRC,在触发该事件之前必须满足一个阈值(字节数)。您好,感谢您的响应,是的,DataReceived事件肯定是在调试模式下触发的。我可以看到我的PCB已成功发送消息“?10”,并且正确的值已存储在阵列中。我在PromptFormation()旁边放了一个记号笔;所以我会看到完整的数组。然后在索引器中也放置一个标记,并按play键仅查看数组为空。PCB在顶部的Form1类中定义,如下所示:pcbSerialPort PCB=new pcbSerialPort()@乔纳森·布朗,这就是你要的。通过在
MsgReceived
方法中创建新实例,可以使用字节数组的普通新实例。您应该研究如何正确使用我的答案中的事件,这将使您摆脱这个问题。@ThorstenDittmar答案很好,您应该阅读它。至少,如果您不想采纳Thorsten的建议并重新设计它,您需要将接收消息的
pcbSerialPort
实例传递给静态
MsgReceieved
函数,然后将其传递给
Form1
的构造函数,这样它就可以存储引用,而不是创建新的(单独的)引用第一,我想我们都同意这样一个事实,即有很多理由不按他的方式去做,其中之一是,实际上独立于UI的类突然与UI建立了连接,因为需要对
Form1.MsgReceived
方法进行硬编码。@ThorstenDittmar:我想(可能吧)OP的想法是能够注入
动作
来处理接收到的数据。当然,它在这里和OP的原始代码中都是硬编码的,但是您可以将
promptFormAction
设置为属性,或者使用构造函数参数设置它,然后删除与UI的硬编码耦合。我不希望每次收到消息时都必须创建Form1的新实例。
public class Form1
{
    pcbSerialPort PCB; // The name of that class I don't know from your code

    public Form1()
    {
        PCB = new pcbSerialPort();
        PCB.MessageReceived += MessageReceived;
    } 

    private void MessageReceived(object sender, pcbSerialPort.MessageReceivedEventArgs e)
    {
        analyzeIncomingMessage(e.Data);
    }

    private void analyzeIncomingMessage(byte[] data)
    {
        if (data[0] == 63)
        {
            setBoardDesignator(data[1], data[2]);
        }
    }
}
Action<pcbSerialPort> promptFormAction = Form1.MsgReceived;

public void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{   
    // as Thorsten noted, you need to rethink this loop anyway
    // what if there aren't at least three bytes to read?
    for (int i = 0; i <= 2; i++) 
    {
        serialPortReceiveBuffer[i] = (uint)serialPort1.ReadByte();
    }

    promptFormAction(this);  
}
public static void MsgReceived(pcbSerialPort pcb)
{
    Form1 _frm = new Form1(pcb);
    _frm.analyzeIncomingMessage();
}
public Form1(pcbSerialPort pcb)
{
    PCB = pcb;
}