簡體   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