Проблема логики при чтении ВСЕХ данных из списка, поступающего из потока в c # - PullRequest
0 голосов
/ 28 января 2019

Я перехожу к первой попытке вопроса.

Мне нужна помощь, чтобы передать данные из списка и передать их другому методу, чтобы каждый раз, когда список получал данные, добавлял их из протектора, он также должен был отправлятьданные в мой новый метод и его в мой список, потому что в этом методе я буду выполнять некоторый анализ, потому что данные из списка представляют собой длинный строковый штрих-код, но мне не нужна помощь при разборе данных, потому что я могу это сделать,Часть, в которой мне нужна только помощь, - это передача данных из потока, который передает их в список, их также следует отправить в мой метод ReadAllData (), поэтому в этом методе я получу данные, а затем выполню синтаксический анализ make return.

Вот метод, в котором список хранится и получает данные из потока через порт 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();
        }
    }
}

Основной класс, который будет вызывать методы из telnetconnectИонный класс или любые другие классы, которые я добавлю.

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();
        }
    }
}

1 Ответ

0 голосов
/ 30 января 2019

Самый простой способ реализовать, не усложняя поток, - просто вызвать событие на listbox, когда к нему добавлен элемент.Проблема в том, что у listbox нет событий, позволяющих это сделать, но вы можете создать свою собственную версию с дюжиной строк кода.

Цель состоит в том, чтобы создать производный элемент управления listbox затем вы добавляете к нему метод для запуска пользовательского события при добавлении элемента и бинго.

Вот пользовательский класс listbox с пользовательским EventArgs.

// 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;
    }       
}

Теперь вам нужно заменить listbox на form вместо ListBoxWithEvents.У вас есть 2 способа сделать это, но я дам вам самый простой.Скомпилируйте свой код и перейдите в окно дизайна для form.В вашем наборе инструментов у вас должен быть элемент управления ListBoxWithEvents, и вы можете просто перетащить свой элемент 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);
}));

Попробуйте, и теперь вы должны запускать это событие каждый раз, когда что-то добавляется в список.

Поскольку вы довольно новичок в программировании, я считаю важным упомянуть, что это событие будет запускаться в потоке пользовательского интерфейса, а не в потоке, который вы создали.Это означает, что он ведет себя нормально, как нажатие на button вызывает событие button_click(object sender, EventArgs e).Никакой специальной темы не было.

...