Problem z wznowieniem wątku - pingowanie

0

Witam.
Mam mianowicie taki problem: po zatrzymaniu wątku t1.suspend(); i próbie wznowienia t1.resume(); procedura pingowania nie jest wznawiana. Dodatkowo po wyjściu z programu bez zatrzymania wątku jest taki error "System.InvalidOperationException: „Elementów Invoke lub BeginInvoke nie można wywołać w formancie do czasu utworzenia uchwytu okna.”.
W skrócie program ma na celu pingowanie określonego hosta, wypisanie wyniku do listview1 i wartosci max_ping, min_ping itd.

Od razu przepraszam was za błędy i pewne zastosowane rozwiązania (aktualnie jestem na etapie nauki z c#, kolejne rozwiązania postaram się implementować z semaforami). Generalnie taki programik sobie wymyśliłem do nauki - przy okazji ułatwiając sobie życie w pracy (potem to rozbuduje o logi, zapisane hosty itd.)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Threading;

namespace pingpong
{
    public partial class Form1 : Form
    {
        public string czas_ping;
        public string host = null; //zmienna przechowujaca host
        bool ping_on = false;
        Ping p = new Ping();
        PingReply reply; // klasa przechowujaca odpowiedzi z ping
        Thread t1;
        byte[] buffer = new byte[0]; //obciazenie pingu
        int timeout = 10000; // timeout pingu
        bool t1_start = false;


        public Form1()
        {
            InitializeComponent();
            t1 = new Thread(pingowanie); //utworzenie watku
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        public void button1_Click(object sender, EventArgs e)
        {
            host = textBox1.Text;


            if (ping_on==false && (host.Length < 3 || host==null))
            {
                MessageBox.Show("Nieprawidłowy host.", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }


            else if (ping_on == false && host.Length > 3)
            {
                //MessageBox.Show("Dzialam", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);


                if (t1_start == false) { t1.Start(); t1_start = true; }
                else{
                    t1.Resume();
                    MessageBox.Show("Dzialam", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);

                }
                ping_on = true;

            }



        }

        
        public void pingowanie()
        {
            long max_ping;
            long min_ping;

            try
            {
                reply = p.Send(host, timeout, buffer);
                min_ping = reply.RoundtripTime;
                max_ping = reply.RoundtripTime;

                //wypisanie najmniejszego pingu
                textBox2.Invoke(new Action(delegate ()
                {
                    textBox2.Text = min_ping.ToString();
                }));

                //wypisanie najwiekszego pingu
                textBox3.Invoke(new Action(delegate ()
                {
                    textBox3.Text = max_ping.ToString();
                }));


                while (true)
                {
                    reply = p.Send(host, timeout, buffer);

                    listView1.Invoke(new Action(delegate ()
                    {

                        // wykonuje polecenie ping i wrzuca wartosc naa liste

                        listView1.Items.Add(reply.RoundtripTime + " ms");

                        //zapewnia widocznosc ostatniego elementu na liscie
                        listView1.Items[listView1.Items.Count - 1].EnsureVisible();
                    }));

                    if (min_ping > reply.RoundtripTime)
                    {
                        min_ping = reply.RoundtripTime;

                        textBox2.Invoke(new Action(delegate ()
                        {
                            textBox2.Text = min_ping.ToString();
                        }));

                    }


                    if (max_ping < reply.RoundtripTime)
                    {
                        max_ping = reply.RoundtripTime;

                        textBox3.Invoke(new Action(delegate ()
                        {
                            textBox3.Text = max_ping.ToString();
                        }));
                    }


                    System.Threading.Thread.Sleep(1000);

                }
            }



            catch (System.ArgumentNullException)
            {
                MessageBox.Show("Pole host nie może pozostać puste.", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }


            catch (System.Net.Sockets.SocketException)
            {
                MessageBox.Show("Host jest nieprawidłowy.", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            catch (System.Net.NetworkInformation.PingException)
            {
                MessageBox.Show("Host jest nieprawidłowy.", "Błąd", MessageBoxButtons.OK, MessageBoxIcon.Error);
                t1.Abort();
                ping_on = false;
            }

            //catch (System.InvalidOperationException) { }
        }



        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }




        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (check_obciazenie.Checked)
            {
                buffer = new byte[1400];
            }

            else buffer = new byte[0];
        }

        public void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            t1.Suspend();
        }

        public void textBox2_TextChanged(object sender, EventArgs e)
        {


        }

        private void textBox3_TextChanged(object sender, EventArgs e)
        {

        }
    }
}

0

Najlepiej nie używaj tego mechanizmu synchnronizacji watków.
Juz od 2.0 jest mocno niezalecany SZCZEGOLNIE przy pracy z zasobami (pliki,siec).

https://msdn.microsoft.com/en-us/library/tttdef8x(v=vs.100).aspx
(sekcja Suspend and Resume (Obsolete)).

Problem z Suspend wynika że możesz zlapać watek w bardzo nieprzyjemnej sytuacji np
sekcja krytyczna, konstruktor klasy, moment miedzy alokowaniem pamieci a przypisaniem do referencji (memory leaki przy zamknieciu).

Lepiej np jakas flaga czy sygnałem wprowadzac watek w waitsleepjoin stan.
Można używac mechanizmow monitora aby probowac pozyskać sterowanie (np okreslony czas).

Do zadan okresowych mozesz uzyc Timerow. Sa (chyba) 2-3 glowne + dodatkowy dla WinForms + WPF.
Mozesz uzywac BackgroundWorker albo Taskow no chyba ze Twoim celem jest nauka konkretnie watkow to ok.
Obecnie od kilku lat odchodzi sie od jawnych watkow.
Są kiedy wymaga tego sytacja, ale w wielu sytuacjach są wypierane przez lżejsze Taski.

P

1 użytkowników online, w tym zalogowanych: 0, gości: 1