1

我有下面的代码,它更新列表视图中的数据,我试图将参数传递到更新列表视图表的主代码中。

我有可以发送突发数据流的外部代码,它在列表中显示相同的值。

以下基于匿名方法,该方法有效,但较早的数据被覆盖。

列表视图太慢了,这会减慢主程序(此处未列出),突发数据会转到此代码并使用单独的线程来处理显示(大约 20 组)。突发数据约为20组dataTX阵列等。

我愿意建议如何解决这个问题。

==================================================== =========================

    public void LIN_Request_Add_Message(bool isCRCIncluded)           // This Add new line for request based message.
    {
        byte[] dataTX = new byte[10];
        dataTX = myLinTools.LinArrayTXArray();
        DateTime d = DateTime.Now;

        this.ReqAddMessageThread = new Thread(delegate() { ReqAddMessageThreadProc(isCRCIncluded, dataTX, d); });          //anonymous method
        this.ReqAddMessageThread.Start();
    }
    #endregion

    private void ReqAddMessageThreadProc(bool isCRCIncluded, byte[] dataTX, DateTime d)
    {
        if (this.OutputView.InvokeRequired)
        {
            test1Callback del = new test1Callback(ReqAddMessageThreadProc);
            this.Invoke(del, new object[] { isCRCIncluded, dataTX,d });
            return;
        }

        if (this.Visible == true)
        {
            SendMessage(this.Handle, WM_SETREDRAW, false, 0);
        }

        int length = myLinTools.LINDataLength;
        int pCRC = 0;
        elem = new ListViewItem(m_Item.ToString());

        elem.SubItems.Add(d.Date.ToShortDateString());
        elem.SubItems.Add(d.ToShortTimeString() + ":" + d.Second.ToString());
        elem.SubItems.Add("");
        for (int i = 0; i < length + 1; i++)
        {
            elem.SubItems.Add(dataTX[i].ToString("X2"));
            pCRC = i;
        }
        for (int i = length; i < 8; i++)
        {
            elem.SubItems.Add("  ");  // fill gaps
        }
        if (isCRCIncluded == true)      // Does the message contains processed CRC data?
        {
            elem.SubItems.Add(dataTX[pCRC + 1].ToString("X2"));
        }
        else                            // No, then make one for display only!!
        {
            Byte CRC = myLinTools.CRC_Processor(false);
            elem.SubItems.Add(CRC.ToString("X2"));
        }
        this.OutputView.Items.Add(elem);
        this.OutputView.EnsureVisible(m_Item);
        if (myLinTools.IsRequestResponse == true)       // Request Message Only
        {
            if (this.Visible == true)                   // Is form open?
            {
                SendMessage(this.Handle, WM_SETREDRAW, true, 0);
                this.Refresh();
            }
        }
        m_Item++;
    }

==================================================== ================================

感谢 KazR,我修改了运行良好的代码,但是它减慢了其他高级程序(称为主程序)的速度,使数据传输到显示数据的程序。此显示程序中的列表视图导致主程序无延迟或暂停地流式传输数据的要求之一。这就是为什么我正在寻找使用线程的方法,因此它将控制释放回主程序,从而运行得更快,但是由于 listview 很慢,因此存在防止数据被下一个线程覆盖的问题。也许我应该考虑一个缓冲区,它仅在主程序中没有活动时更新。

我不想使用虚拟,我愿意接受其他建议。

==================================================== =================================

delegate void ReqAddMessageTCallback(bool isCRCIncluded, byte[] dataTX, DateTime d);
#region//==================================================LIN_Request_Add_Message
public void LIN_Request_Add_Message(bool isCRCIncluded)           // This Add new line for request based message.
{
    byte[] dataTX = new byte[10];
    dataTX = myLinTools.LinArrayTXArray();
    DateTime d = DateTime.Now;
    ReqAddMessageThreadProc(isCRCIncluded, dataTX, d);

}
#endregion

#region//==================================================ReqAddMessageThreadProc
private void ReqAddMessageThreadProc(bool isCRCIncluded, byte[] dataTX, DateTime d)
{
    if (this.OutputView.InvokeRequired)
    {
        ReqAddMessageTCallback del = new ReqAddMessageTCallback(ReqAddMessageThreadProc);
        this.BeginInvoke(del, new object[] { isCRCIncluded, dataTX, d });
        return;
    }

    if (this.Visible == true)
    {
        SendMessage(this.Handle, WM_SETREDRAW, false, 0);
    }

    int length = myLinTools.LINDataLength;
    int pCRC = 0;
    elem = new ListViewItem(m_Item.ToString());
4

2 回答 2

1

从您的代码示例看来,您每次接收数据时都在创建一个新的 Thread 对象,并且该线程所做的所有事情都是调用 ReqAddMessageThreadProc 方法。假设没有在主 UI 线程中调用 LIN_Request_Add_Message,您可以尝试删除线程创建和启动调用,将它们替换为直接调用 ReqAddMessageThreadProc 并使用 BeginInvoke 而不是 Invoke。

例如

public void LIN_Request_Add_Message(bool isCRCIncluded)           // This Add new line for request based message.
{
    byte[] dataTX = new byte[10];
    dataTX = myLinTools.LinArrayTXArray();
    DateTime d = DateTime.Now;

    ReqAddMessageThreadProc(isCRCIncluded, dataTX, d);

}
#endregion

private void ReqAddMessageThreadProc(bool isCRCIncluded, byte[] dataTX, DateTime d)
{
    if (this.OutputView.InvokeRequired)
    {
        test1Callback del = new test1Callback(ReqAddMessageThreadProc);
        this.BeginInvoke(del, new object[] { isCRCIncluded, dataTX,d });
        return;
    }

ETC...

BeginInvoke 调用是 Invoke 的异步版本,这应该消除每次接收新数据时使用单独的新线程对象的需要。

于 2012-05-31T09:46:39.797 回答
0

你应该让你的 ListView 虚拟。然后你可以用你的线程全速操作,列表视图将只显示当前可见的项目。如果您确实将内容附加到 ListView 而不是每次添加内容时都强制使其可见,您可以让用户决定他何时想要向下滚动。他确实看到了什么时候添加了东西,因为在添加项目时滚动条变得越来越小。

通过这种方式,您可以毫无问题地显示数百万个条目,并且您将摆脱通过 SendMessage 调用、重绘、刷新列表视图。这是一个虚拟列表视图示例,您可以如何更改它。

通过这样做,您的代码将变得更简单和更快,因为您不会将后台数据处理与 UI 内容混合在一起。例如,排序可以在原始数据数组级别完成,而无需在 UI 中执行任何操作,除非触发它。

于 2012-05-31T11:04:50.160 回答