Разрешить основной (графический) поток при выполнении задачи, а затем обновить таблицу - PullRequest
0 голосов
/ 23 октября 2018

Я использую winform, чтобы попытаться собрать статус онлайн / офлайн каждого IP в сети, поэтому я использую запрос ping, если он отвечает, он помечает IP как онлайн, а затем переходит.Единственная проблема - ожидание до 255 ответов, после получения всех 255 ответов. Я хочу, чтобы он заполнил представление таблицы данных.

Мне удалось заставить все это работать, но единственным недостатком является то, что графический интерфейс зависаетвыполняя этот процесс, я решил использовать отдельный поток со следующим выражением

Thread T1 = new Thread(PingHost)
T1.run();

PingHost делает, как следует из названия, пингует все хосты и решает, подключен он или нет.Проблема в том, что я пытался обновить таблицу dgv из потока, естественно, dgv заблокирован в главном потоке.

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

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

Код основного потока с использованием задач

List<string> everything = new List<string>();

        int i = 0;


        Task<List<string>> task1 = Task<List<string>>.Factory.StartNew(PingHost);
        everything = task1.Result;
        foreach(var item in everything)
        {
            var index = dataGridView1.Rows.Add();
            dataGridView1.Rows[i].Cells["IP"].Value = item;
            i++;
        }

И это поток моего метода PingHost

bool pingable = false;
        Ping pinger = null;
        int i = 0;

        string ip;
        while (i < 255)
        {
             ip = "192.168.0." + i;
            try
            {
                pinger = new Ping();
                PingReply reply = pinger.Send(ip, 8);
                pingable = reply.Status == IPStatus.Success;
            }
            catch (PingException)
            {
                MessageBox.Show("ERROR");
                // Discard PingExceptions and return false;
            }
            finally
            {
                if (pinger != null)
                {
                    pinger.Dispose();
                }
            }
            if (pingable)
            {
                checkedIP.Add(ip + ": ONLINE");
            }
            else
            {
            checkedIP.Add(ip + ": OFFLINE");

            }
            i++;
        }
        return checkedIP;

1 Ответ

0 голосов
/ 23 октября 2018

Это может быть немного излишним, но я только что разработал решение.По сути, я создал новый класс для проверки связи с событием, которое срабатывает после каждого возвращенного запроса Ping. Это событие использует пользовательский EventArgs для возврата IP-адреса, который был только что проверен, и если он подключен или нет.Затем я подписался на это событие в моей ветке GUI и просто обновил GUI.Вот некоторый код:

Это мой класс Pinger, отвечающий за пинг реальных компьютеров:

class Pinger
{
    public event EventHandler<PingReturnedEventArgs> OnPingReturned;

    public void PingNetwork()
    {
        for (int i = 1; i <= 255; i++)
        {
            string ip = $"192.168.0.{i}";

            Ping ping = new Ping();

            try
            {
                PingReply reply = ping.Send(IPAddress.Parse(ip));
                TriggerEvent(reply?.Address.ToString(), true);
            }
            catch (Exception)
            {
                TriggerEvent(ip, false);
            }
        }
    }

    private void TriggerEvent(string ip, bool online)
    {
        if (OnPingReturned == null) return;

        PingReturnedEventArgs args = new PingReturnedEventArgs(ip, online);
        OnPingReturned(this, args);
    }
}

Мои пользовательские EventArgs:

class PingReturnedEventArgs : EventArgs
{
    public string Ip { get; private set; }

    public bool Online { get; private set; }

    private PingReturnedEventArgs() { }

    public PingReturnedEventArgs(string ip, bool online)
    {
        Ip = ip;
        Online = online;
    }
}

И, наконец, вот как яЯ на самом деле использую все это:

Pinger pinger = new Pinger();
pinger.OnPingReturned += Your event handler to update the GUI

// I recommend doing it like this so you can stop the Thread at a later time
// Maybe with like a cancel button
Thread pingThread = new Thread(pinger.PingNetwork);
pingThread.Start();

Обработчик событий выглядит следующим образом private void PingReturnedHandler(object sender, PingReturnedEventArgs args)

Два основных преимущества этого состоят в том, что 1. поток GUI остается разблокированным, то естьGUI будет по-прежнему реагировать на ввод данных пользователем, и 2. это процедурно (при каждом завершении ping) инициирует событие, означающее, что если для проверки связи с всеми ПК требуется много времени, вам не нужно ждать завершения всей работы, прежде чем пользовательвидит что-то

...