Создание потоков для подключения tcp C#

107
03 октября 2019, 11:20

Столкнулся с проблемой, не знаю как реализовать.

Есть treeView, данные берутся из базы данных. В узле хранятся данные для tcp подключения. Я хочу, чтобы при загрузке формы опросилось каждое соединение и опрашивались постоянно с каким-то интервалом. И по нажатию на узел тоже открывалось соединение и с ним я уже буду работать.

Я написал функцию для опроса устройства, добавил её в поток, но всё-равно при неверном подключении - очень долго поток обрабатывается.

А как сделать что-бы они все опрашивались - я вообще не понимаю...

Может кто-нибудь сможет помочь. Буду очень благодарен.

Это моё подключение.

public void connect()
    {
        this.Invoke((MethodInvoker)delegate ()
        {
            string[] IpHERE;
            TreeNode currentNode = treeView1.SelectedNode;
            IpHERE = currentNode.Text.Split(' ');
            Modbus mb = new Modbus();
            Regex regIP = new Regex(@"\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b");
            if (regIP.IsMatch(IpHERE[1]) && IpHERE[1].Length != 0 && IpHERE[4].Length != 0 && IpHERE[9].Length != 0 && IpHERE[11].Length != 0 && (mb.OpenTCP(IpHERE[1], IpHERE[4], IpHERE[9], IpHERE[11])))
            {
                currentNode.SelectedImageIndex = 3;
                dataGridView1.Visible = true;
                mb.CloseTCP();
            }
            else
            {
                currentNode.SelectedImageIndex = 4;
            }
        });
        Thread.Sleep(100);
    }

Это действие при нажатии

private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
    {
        string[] IpHERE;
        TreeNode currentNode1 = treeView1.SelectedNode;
        IpHERE = currentNode1.Text.Split(' ');
        Thread thread = new Thread(new ThreadStart(connect));
        thread.Start();
    }

Я сделал гифки с подключением. Первая с успешным подключением а вторая нет(заснял не до конца, там долго).

Answer 1

//класс устройства
class Device
{
    public string IpAddress { get; set; }
    public string Port { get; set; }
    public string Name { get; set; }
}

С БД будем работать в отдельном классе. Перед создание объекта устройства будем там же проверять данные.

//класс для работы с БД
class DataContext
{
    public async Task<List<Device>> GetDevicesAsync()
    {
        DataTable table = await GetTableDevicesAsync();
        var result = new List<Device>();
        foreach (DataRow row in table.Rows)
        {
            var address = row["Address"].ToString();
            var port = row["Port"].ToString();
            var name = row["Name"].ToString();
            //если данные верны
            if (IsCorrect(address, port, name))
            {
                result.Add(new Device { IpAddress = address, Port = port, Name = name });
            }
        }
        return result;
    }
    private bool IsCorrect(string address, string port, string name)
    {
        //здесь делаем вашу проверку
        //c помощью вашего
        //Regex regIP = new Regex("...");
        //проверка пройдена
        return true;
    }
    //...
}

Для ноды в TreeView создадим класс

class DeviceTreeNode : TreeNode
{
    public Device Device { get; private set; }
    public DeviceTreeNode(Device device)
    {
        Device = device ?? throw new ArgumentNullException(nameof(device));
        this.Text = $"IP:{Device.IpAddress}-Порт:{Device.Port}-Устройство:{Device.Name}";
    }
}

Так выглядит код формы

public partial class MainView : Form
{
    //класс работы с БД
    private readonly DataContext _data = new DataContext();
    //флаг загрузки формы
    private bool _isFirsLoading = true;
    //флаг опроса всех нод
    private bool _isChecking = false;
    public MainView()
    {
        InitializeComponent();
        //загрузка данных
        LoadData();
        this.StartPosition = FormStartPosition.CenterScreen;
        this.Text = "Пример";
        //подписка
        _treeViewDevices.AfterSelect += TreeViewIpAddresses_AfterSelect;
        _buttonCheckAll.Click += ButtonCheckAll_Click;
        _buttonCancel.Click += ButtonCancel_Click;
    }
    /// <summary>
    /// Загрузка данных из БД
    /// Создание нод для TreeView
    /// </summary>
    private async void LoadData()
    {
        //получаем коллекцию устройств из БД
        List<Device> devices = await _data.GetDevicesAsync();
        //создаем ноды и наполняем TreeView
        foreach (var device in devices)
        {
            var node = new DeviceTreeNode(device);
            node.ImageIndex = 0;
            node.SelectedImageIndex = 1;
            _treeViewDevices.Nodes.Add(node);
        }
    }
    /// <summary>
    /// Выбор ноды в TreeView
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void TreeViewIpAddresses_AfterSelect(object sender, TreeViewEventArgs e)
    {
        //надо ли что-то делать
        if (_isFirsLoading || _isChecking)
        {
            _isFirsLoading = false;
            return;
        }
        await ConnectToDevice(_treeViewDevices.SelectedNode);
    }
    /// <summary>
    /// Соединение с выделенным устройством
    /// </summary>
    /// <param name="node"></param>
    /// <returns></returns>
    private async Task ConnectToDevice(TreeNode node)
    {
        //приводим ноду к нашему типу
        var devNode = node as DeviceTreeNode;
        //пытаемся соединиться
        var modbus = new Modbus(devNode.Device.IpAddress, devNode.Device.Port);
        bool connected = await Task.Run(() => modbus.OpenTCP());
        if (connected)
        {
            Debug.WriteLine($"Адрес {devNode.Device.IpAddress} доступен");
            devNode.SelectedImageIndex = 2;
            await Task.Run(() => modbus.CloseTCP());
        }
        else
        {
            Debug.WriteLine($"Адрес {devNode.Device.IpAddress} недоступен");
            devNode.SelectedImageIndex = 3;
        }
    }
    /// <summary>
    /// Опрос всех устройств
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private async void ButtonCheckAll_Click(object sender, EventArgs e)
    {
        _isChecking = true;
        _buttonCancel.Enabled = true;
        _buttonCheckAll.Enabled = false;
        foreach (TreeNode node in _treeViewDevices.Nodes)
        {
            if (!_isChecking) break;
            // выделяем ноду
            _treeViewDevices.SelectedNode = node;
            //пытаемся соединится
            await ConnectToDevice(node);
            //пауза чтоб успела отобразиться иконка
            await Task.Delay(500);
        }
        _isChecking = false;
        _buttonCancel.Enabled = false;
        _buttonCheckAll.Enabled = true;
    }
    private void ButtonCancel_Click(object sender, EventArgs e)
    {
        _isChecking = false;
    }
}

Пример целиком можно найти здесь

READ ALSO
Исключение ArgumentException: Элемент с тем же ключом уже был добавлен

Исключение ArgumentException: Элемент с тем же ключом уже был добавлен

возникла ошибка ArgumentException: Элемент с тем же ключом уже был добавлен при добавлении словаря

159
Открытие сформированных документов в MS Office 2007 и более ранней версии

Открытие сформированных документов в MS Office 2007 и более ранней версии

Использую OpenXML SDK для последующего формирования word файла на с#, полученный сформированный файл имеет расширениеdocx и без проблем открывается...

98
Как отключить переход в спящий режим, когда работает программа?

Как отключить переход в спящий режим, когда работает программа?

Написал программу, которая должна работать круглосуточно, поставил ее на ноутбук

194
Перегрузка унарного оператора &#171;!&#187;

Перегрузка унарного оператора «!»

Как правильно осуществить перегрузку и использовать в дальнейшем данный логический оператор «!»Если сравнивается следующие: если заданная...

113