繁体   English   中英

从列表框读取来自C#中线程的所有数据的逻辑问题

[英]Logic issue on reading ALL data from the from the listbox that is coming from thread in c#

我正在修改第一个问题尝试。

我需要帮助将列表框中的数据传递给另一个方法,因此,每次列表框获取数据时,都需要从胎面将其添加到数据中,它还应该将该数据发送到我的新方法以及我的列表中,因为在这种方法中,我会正在做一些解析,因为列表框中的数据是长字符串条形码,但我不需要解析数据的帮助,因为我可以做到这一点,我需要帮助的部分只是将数据从传递给它的线程传递给列表框,它也应该发送到我的方法ReadAllData(),因此在该方法中,我将接收到数据,然后进行解析以进行返回。

这是存储列表框并从telnet端口23的线程接收数据的方法

这是我需要将lst_BarcodeScan中的数据发送到方法ReadAllData方法并将其存储到我的列表中的代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.Remoting.Messaging;
using System.Security.Authentication.ExtendedProtection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace BarcodeReceivingApp
{
    public class TelnetConnection
    {
        private Thread _readWriteThread;
        private TcpClient _client;
        private NetworkStream _networkStream;
        private string _hostname;
        private int _port;
        private BarcodeReceivingForm _form;
        private bool _isExiting = false;

        public TelnetConnection(string hostname, int port)
        {
            this._hostname = hostname;
            this._port = port;
        }

        public TelnetConnection()
        {

        }

        public void ServerSocket(string ip, int port, BarcodeReceivingForm f)
        {

            this._form = f;
            try
            {
                _client = new TcpClient(ip, port);
            }
            catch (SocketException)
            {
                MessageBox.Show(@"Failed to connect to server");
                return;
            }


            _networkStream = _client.GetStream();
            _readWriteThread = new Thread(ReadWrite);
            //_readWriteThread = new Thread(() => ReadWrite(f));
            _readWriteThread.Start();
        }


        public void Exit()
        {
            _isExiting = true;
        }

        public void ReadWrite()
        {

            var received = "";
            do
            {
                received = Read();
                if (received == null)
                    break;

                if (_form.lst_BarcodeScan.InvokeRequired)
                {
                    _form.lst_BarcodeScan.Invoke(new MethodInvoker(delegate
                    {
                        _form.lst_BarcodeScan.Items.Add(received + Environment.NewLine);
                    }));
                }    

            } while (!_isExiting);



            CloseConnection();


        }

    public List<string> ReadAllData()
    {
        var obtainData = new List<string>();



       return obtainData;
    }

        public string Read()
        {
            var data = new byte[1024];
            var received = "";

            var size = _networkStream.Read(data, 0, data.Length);
            if (size == 0)
                return null;

            received = Encoding.ASCII.GetString(data, 0, size);

            return received;
        }

        public void CloseConnection()
        {
            MessageBox.Show(@"Closed Connection",@"Important Message");
            _networkStream.Close();
            _client.Close();
        }
    }
}

主类,它将从telnetconnection类或我将添加的任何其他类中调用方法。

using System;
using System.Windows.Forms;

namespace BarcodeReceivingApp
{
    public partial class BarcodeReceivingForm : Form
    {
        //GLOBAL VARIABLES
        private const string Hostname = "myip";
        private const int Port = 23;
        private TelnetConnection _connection;


        public BarcodeReceivingForm()
        {
            InitializeComponent();

            //FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            WindowState = FormWindowState.Maximized;
        }

        private void btn_ConnectT_Click(object sender, EventArgs e)
        {
            _connection = new TelnetConnection(Hostname, Port);
            _connection.ServerSocket(Hostname, Port, this);

        }

        private void btn_StopConnection_Click(object sender, EventArgs e)
        {
            //_connection = new TelnetConnection(Hostname, Port);
            //_connection.ServerSocket(Hostname, Port, this);
            _connection.Exit();
        }

        private void btn_RemoveItemFromListAt_Click(object sender, EventArgs e)
        {
            for (var i = lst_BarcodeScan.SelectedIndices.Count - 1; i >= 0; i--)
            {
                lst_BarcodeScan.Items.RemoveAt(lst_BarcodeScan.SelectedIndices[i]);
            }
        }

        private void BarcodeReceivingForm_Load(object sender, EventArgs e)
        {
            lst_BarcodeScan.SelectionMode = SelectionMode.MultiSimple;
        }

        private void btn_ApplicationSettings_Click(object sender, EventArgs e)
        {
            var bcSettingsForm = new BarcodeReceivingSettingsForm();
            bcSettingsForm.Show();
        }

        private void btn_ClearBarcodeList_Click(object sender, EventArgs e)
        {
            lst_BarcodeScan.Items.Clear();
        }
    }
}

在不增加线程复杂性的情况下实现的最简单方法是,在将和项添加到listbox时在listbox上引发一个事件。 问题是listbox没有任何允许执行此操作的事件,但是您可以使用十几行代码创建自己的版本。

目标是创建listbox的派生控件,然后向其中添加一个方法,以在添加项目和宾果游戏时触发自定义事件。

这是带有自定义EventArgs的自定义listbox类。

// custom override class over the list box so we can create an event when items are added
public class ListBoxWithEvents : ListBox
{
    // the event you need to bind to know when items are added
    public event EventHandler<ListBoxItemEventArgs> ItemAdded;

    // method to call to add items instead of lst.Items.Add(x);
    public void AddItem(object data)
    {
        // add the item normally to the internal list
        var index = Items.Add(data);

        // invoke the event to notify the binded handlers
        InvokeItemAdded(index);
    }

    public void InvokeItemAdded(int index)
    {
        // invoke the event if binded anywhere
        ItemAdded?.Invoke(this, new ListBoxItemEventArgs(index));
    }
}

// basic event handler that will hold the index of the item added
public class ListBoxItemEventArgs : EventArgs
{
    public int Index { get; set; } = -1;
    public ListBoxItemEventArgs(int index)
    {
        Index = index;
    }       
}

现在,您需要使用ListBoxWithEvents来更改form上的listbox 您有2种方法可以做到这一点,但我会给您最简单的方法。 编译代码,然后进入form的设计窗口。 在您的工具箱中,您现在应该拥有ListBoxWithEvents控件,您可以简单地拖放form并替换您拥有的form 由于它是从listbox派生的,因此它具有其他功能。 它没有丢失以前的任何东西。

现在您需要更改2件事。 在您的form选择新的ListBoxWithEvents控件,然后进入属性事件,您将找到名为ItemAdded的新事件,您可以双击该事件,它应该创建一个如下所示的事件。 我还抛出了一个示例MessageBox ,它显示了您所需要的全部。

private void ListBox1_ItemAdded(object sender, ListBoxItemEventArgs e)
{
    MessageBox.Show("Item was added at index " + e.Index + " and the value is " + listBox1.Items[e.Index].ToString());
}

最后,为了触发该事件,您需要使用新方法lst.AddItem(object); 而不是lst.Items.Add(object); 因此,根据您的示例代码,您需要更改以下内容:

_form.lst_BarcodeScan.Invoke(new MethodInvoker(delegate
{
    _form.lst_BarcodeScan.Items.Add(received + Environment.NewLine);
}));

对此:

_form.lst_BarcodeScan.Invoke(new MethodInvoker(delegate
{
    _form.lst_BarcodeScan.AddItem(received + Environment.NewLine);
}));

尝试一下,现在每次添加到列表中时,都应该触发该事件。

由于您是编程的新手,因此我发现必须提及此事件将在UI线程而不是您创建的线程上触发,这一点很重要。 这意味着它的行为就像在单击button触发button_click(object sender, EventArgs e)事件一样。 无需任何特殊线程。

暂无
暂无

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

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