Пользовательский интерфейс не обновляется при прохождении через IP-адреса - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть простая работа, при нажатии кнопки она получает все сетевые IP-адреса из диапазона, l oop через них и помещает активную в список. При выполнении процесса будет показана панель, на которой будет отображаться IP-адрес, который проверяется. Код работает нормально, но форма зависает, приложение go не отвечает и IP-адрес не отображается, даже панель не отображается. как это сделать? мой код:

private void btnAutoSearch_Click(object sender, EventArgs e)
    {
        panel_Search.Visible = true; // Not Working
        Cursor.Current = Cursors.WaitCursor;

        string ipBase = getIPAddress();
        string[] ipParts = ipBase.Split('.');
        ipBase = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".";



        for (int i = 1; i < 255; i++)
        {
            string ip = ipBase + i.ToString();
            Ping p = new Ping();                
            PingReply pingresult = p.Send(ip, 100);
            if (pingresult.Status == IPStatus.Success)
            {
                lstIPs.Add(ip);
                lblConnecting.Text = ip;  // Not Working

            }

        }


        GridConn.Rows.Clear();
        foreach (string s in lstIPs)
        {
            Device obj = new Device();
            obj.IPAddress = s;
            lblConnecting.Text = s;
            int vSMSLimit = 0;
            int.TryParse(txtSMSLimit.Text, out vSMSLimit);
            obj.SMSLimit = 0;
            if (obj.ConnectToHostServer())
            {
                obj.SendConnectionMessage();
                obj.ReceiveConnectionMessage();
                MyDevices.lst.Add(obj);
                GridConn.Rows.Add(true, obj.IPAddress, obj.PhoneModel, obj.PhoneStatus, obj.SoftwareVersion);
            }
        }


         Cursor.Current = Cursors.Default;
        panel_Search.Visible = false;
    }

Ответы [ 3 ]

0 голосов
/ 27 апреля 2020

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

Наилучшее Практика заключается в том, что обработчики событий принимают поток пользовательского интерфейса в течение очень короткого времени.

Когда вам нужно выполнить длительные задачи из-за взаимодействия с пользователем, вы должны выполнить задачу в другом потоке, вы не должны использовать поток пользовательского интерфейса в течение длительного времени. запущенные задачи.

Вы можете использовать BackgroundWorker для перемещения задачи в другой поток, но лучше использовать асинхронные обработчики событий.

Например:

private async void myButton_Click(object sender, EventArgs e)
{
    await PerformLongRunningTaskAsync();
    //TODO: update UI after completing task

    await Task.Run(() => PerformLongRunningTaskSynchronously());
    //TODO: update UI after completing task;
}

private async Task PerformLongRunnigTaskAsync() {
   //TODO: implement this async method
}

private void PerformLongRunningTaskSynchronously() {
  //TODO: implement this synchronus method
}

Ваш код должен быть как то так:

private async void btnAutoSearch_Click(object sender, EventArgs e)
    {
        panel_Search.Visible = true; // Not Working
        Cursor.Current = Cursors.WaitCursor;

        string ipBase = getIPAddress();
        string[] ipParts = ipBase.Split('.');
        ipBase = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".";



        for (int i = 1; i < 255; i++)
        {
            string ip = ipBase + i.ToString();
            Ping p = new Ping();                
            PingReply pingresult = await p.SendPingAsync(ip, 100);
            if (pingresult.Status == IPStatus.Success)
            {
                lstIPs.Add(ip);
                lblConnecting.Text = ip;  // Not Working

            }

        }


        GridConn.Rows.Clear();
        foreach (string s in lstIPs)
        {
            Device obj = new Device();
            obj.IPAddress = s;
            lblConnecting.Text = s;
            int vSMSLimit = 0;
            int.TryParse(txtSMSLimit.Text, out vSMSLimit);
            obj.SMSLimit = 0;
            if (await Task.Run(() => obj.ConnectToHostServer())
            {
                await Task.Run(() => obj.SendConnectionMessage());
                await Task.Run(() => obj.ReceiveConnectionMessage());
                MyDevices.lst.Add(obj);
                GridConn.Rows.Add(true, obj.IPAddress, obj.PhoneModel, obj.PhoneStatus, obj.SoftwareVersion);
            }
        }


         Cursor.Current = Cursors.Default;
        panel_Search.Visible = false;
    }
0 голосов
/ 27 апреля 2020

Вот как я сделал работу благодаря Брайану Роджерсу,

 private void btnAutoSearch_Click(object sender, EventArgs e)
    {

        backgroundWorker1.WorkerSupportsCancellation = true;


        if (backgroundWorker1.IsBusy != true)
        {
            // Start the asynchronous operation.
            backgroundWorker1.RunWorkerAsync();
        }

    }

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        for (int j = 1; j <= 10; j++)
        {
            if (worker.CancellationPending == true)
            {
                e.Cancel = true;
                break;
            }
            else
            {
                Cursor.Current = Cursors.WaitCursor;
                panel_Search.Location = new Point(380, 72);
                // Perform a time consuming operation and report progress.
                string ipBase = getIPAddress();
                string[] ipParts = ipBase.Split('.');
                ipBase = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".";



                for (int i = 1; i < 255; i++)
                {
                    string ip = ipBase + i.ToString();
                    Ping p = new Ping();                                                
PingReply pingresult = p.Send(ip, 100);
                    if (pingresult.Status == IPStatus.Success)
                    {
                        lstIPs.Add(ip);                            
                        lblConnecting.Text = ip;
                        //listBox1.Items.Add(ip);                
                    }

                }




                GridConn.Rows.Clear();
                foreach (string s in lstIPs)
                {
                    Device obj = new Device();
                    obj.IPAddress = s;
                    lblConnecting.Text = s;
                    int vSMSLimit = 0;
                    int.TryParse(txtSMSLimit.Text, out vSMSLimit);
                    obj.SMSLimit = 0;
                    if (obj.ConnectToHostServer())
                    {
                        obj.SendConnectionMessage();
                        obj.ReceiveConnectionMessage();
                        MyDevices.lst.Add(obj);
                        GridConn.Rows.Add(true, obj.IPAddress, obj.PhoneModel, obj.PhoneStatus, obj.SoftwareVersion);
                    }
                }

                Cursor.Current = Cursors.Default;
                panel_Search.Location = new Point(333, 252);

            }
        }
    }
0 голосов
/ 27 апреля 2020

Проблема заключается в том, что пользовательский интерфейс должен быть обновлен из потока «Main» (всегда называемого потоком пользовательского интерфейса), но если вы выполняете другую обработку в этом потоке, то сам пользовательский интерфейс блокируется. Поэтому вы должны поместить долго выполняющийся процесс в другой поток.

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

К счастью, есть простой способ сделать это, используя класс BackgroundWorker в C#, который может вам сильно помочь. Но вам нужно разделить ваш пользовательский интерфейс и фоновые задачи.

//Define worker
BackgroundWorker myBGWorker;


//Initalise worker and start it from your button
private void btnAutoSearch_Click(object sender, EventArgs e)
{
    panel_Search.Visible = true; // Not Working
    Cursor.Current = Cursors.WaitCursor;

    myBGWorker = new BackgroundWorker()

    //This method will execute your processing on a background thread
    myBGWorker.DoWork += new DoWorkEventHandler(bgw_DoWork);

    //This method will execute when your background worker finishes
    //It runs on the Main/UI thread
    myBGWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);

    //This method will execute when the background thread wants to update the progress
    //It runs on the Main/UI Thread
    myBGWorker.ProgressChanged += new ProgressChangedEventHandler(bgw_ProgressChanged);

    //Tell it we will be reporting progress
    myBGWorker.WorkerReportsProgress = true;

    //Start!
    myBGWorker.RunWorkerAsync()
}

private void bgw_DoWork(object sender, DoWorkEventArgs e)  
{  
        string ipBase = getIPAddress();
        string[] ipParts = ipBase.Split('.');
        ipBase = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".";

        for (int i = 1; i < 255; i++)
        {
            string ip = ipBase + i.ToString();
            Ping p = new Ping();                
            PingReply pingresult = p.Send(ip, 100);
            if (pingresult.Status == IPStatus.Success)
            {
                lstIPs.Add(ip);

                //Below reports the progress.  The number shouuld represent the percentage of process, the object can be anything you want
                double percentDone = (100.0 / 255.0) * i;            
                e.ReportProgress(Convert.ToInt32(percentDone), ip);
            }

        }
}  

private void bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    lblConnecting.Text = e.UserState as string;  
}


private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{
    if (e.Cancelled) 
        MessageBox.Show("Operation was canceled");  
    else if (e.Error != null) 
        MessageBox.Show(e.Error.Message);  
    else 
    {
       GridConn.Rows.Clear();
        foreach (string s in lstIPs)
        {
            Device obj = new Device();
            obj.IPAddress = s;
            lblConnecting.Text = s;
            int vSMSLimit = 0;
            int.TryParse(txtSMSLimit.Text, out vSMSLimit);
            obj.SMSLimit = 0;
            if (obj.ConnectToHostServer())
            {
                obj.SendConnectionMessage();
                obj.ReceiveConnectionMessage();
                MyDevices.lst.Add(obj);
                GridConn.Rows.Add(true, obj.IPAddress, obj.PhoneModel, obj.PhoneStatus, obj.SoftwareVersion);
            }
        }

        Cursor.Current = Cursors.Default;
        panel_Search.Visible = false;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...