none
Многопоточность RRS feed

  • Вопрос

  • Здравствуйте подскажите пожалуйста у меня курсовой - разработать сканер портов с использованием потоков

    потоки бы выполняли какую- то функцию сканирования портов

    результат выполнения бы отображался в listview

    но форма при этом отвечала на действия пользователей то есть можно было бы прокрутить listview или передвинуть форму

    Thread[] t = new Thread[10];

    for(int i=0;i<10;i++)

    { t= new Thread(new ThreadStart(Run)); t.Start();

    t.IsBackground = true; }

    В общем создаю массив потоков назначаю им задачу и назначаю в фоновый режим

    но форма подвисает и не отвечает на мои действия что делать?

    мне посоветовали разблокировать форму но я не понимаю как это сделать

    спасибо за любую помощь

    9 ноября 2011 г. 20:21

Ответы

  • > я пробовал создать 10 потоков и каждому назначить по 12000 портов но потоки с циклами работать не хотят


    using System.Threading.Tasks;
    using System.Collections.Concurrent;
    ...
    Parallel.ForEach(Partitioner.Create(0, 65500, 12000), (range, state) =>
    {
        for (int i = range.Item1; i < range.Item2; i++)
        {
            ...
        }
    });
    

    • Помечено в качестве ответа lindstorm 13 ноября 2011 г. 21:33
    13 ноября 2011 г. 19:06
  • using System.ComponentModel;
    using System.Windows.Forms;
    using System.Threading.Tasks;
    using System.Net.Sockets;
    using System.Net;
    
    namespace WindowsFormsApplication136
    {
        public partial class Form1 : Form
        {
            int fromPort = 1;
            int toPort = 1000/*65535*/;
            int timeout = 200;
            int threads = 10;
            string host = "google.com";
    
            IPAddress remoteHost;
            ListView lv;
            ProgressBar pb;
            BackgroundWorker bw;
    
            public Form1()
            {
                lv = new ListView();
                lv.Parent = this;
                lv.Dock = DockStyle.Fill;
                lv.View = View.List;
    
                pb = new ProgressBar();
                pb.Parent = this;
                pb.Dock = DockStyle.Bottom;
                pb.Maximum = toPort  - fromPort + 1;
    
                remoteHost = Dns.Resolve(host).AddressList[0];
    
                bw = new BackgroundWorker();
                bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                bw.RunWorkerAsync();
                bw.WorkerReportsProgress = true;
                bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            }
    
            void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                pb.Value = e.ProgressPercentage;
                Text = "Processed " + e.ProgressPercentage + " ports";
            }
    
            void bw_DoWork(object sender, DoWorkEventArgs e)
            {
                int counter = 0;
                ParallelOptions po = new ParallelOptions();
                po.MaxDegreeOfParallelism = threads;
    
                Parallel.For(fromPort, toPort + 1, po, (port) =>
                    {
                        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        var res = socket.BeginConnect(remoteHost, port, null, socket);
                        res.AsyncWaitHandle.WaitOne(timeout, true);
                        Invoke(new MethodInvoker(() => OnPortIsAccessible(port, socket.Connected)));
                        if (socket.Connected)
                            socket.Close();
                        lock(bw) counter++;
                        bw.ReportProgress(counter);
                    }
                );
                Invoke(new MethodInvoker(() => Text = "Scanning is completed."));
            }
    
            void OnPortIsAccessible(int port, bool isAccessible)
            {
                if (isAccessible)
                    lv.Items.Add("Port " + port + " is accessible");
            }
        }
    }
    
    

    • Помечено в качестве ответа lindstorm 13 ноября 2011 г. 21:34
    13 ноября 2011 г. 20:10

Все ответы

  • > В общем создаю массив потоков назначаю им задачу и назначаю в фоновый режим но форма подвисает и не отвечает на мои действия что делать?


    сканирование выполнять с помощью BackgroundWorker Class в DoWork
    результат выводить из ProgressChanged

    + см. TPL (Task Parallel Library
    • Изменено Malobukv 9 ноября 2011 г. 20:41
    • Предложено в качестве ответа Abolmasov Dmitry 11 ноября 2011 г. 7:16
    9 ноября 2011 г. 20:39
  • Странно, что зависает. Вы можете привести метод Run? Как и где выполняете обновление данных на форме?


    Для связи [mail]
    11 ноября 2011 г. 7:16
  • Моя задача - просканировать порты
    Я создаю массив из 10 потоков и каждому из них назначаю начальный и конечный порт 
    Например 1 поток - 100 - 200, 2 - 200 - 300 и т.д.
    В функции Run v1 v2 -  как раз начальный и конечный порты
    public void Run(int v, int v2)
                {
                    for (i = v; i <= v2; i++)
                    {
                       IPEndPoint IPEP = new IPEndPoint(sd, i); //подключение к удаленному хосту
                        // создаем сокет и инициализируем его
                        Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        IAsyncResult IAR = sock.BeginConnect(IPEP, new AsyncCallback(ConnectCallback), sock);
                      если порт не отвечает - он закрыт
                        if (!IAR.AsyncWaitHandle.WaitOne(10, false))//блокирует текущий поток до получения сигнала текущим объектом
                        {
                            //соединяемся с сервером
                            //sock.Connect(IPEP);
                            sock.Close();
                            s2 = "Порт " + i.ToString() + "закрыт";
                            form.BeginInvoke(form.m_GetClosePorts, new Object[] { s2, 1 });
                        }
                        else
                        {
                            sock.Close();
                            s = "Порт " + i.ToString() + "открыт";
                            form.BeginInvoke(form.m_GetOpenPorts, new Object[] { s, 1 });
                        }
                    }
    вывод в форму закрытых портов - у открытых вывод аналогичен
    public void GetClosePorts(string s, int index)
            {
                try
                {
                    listView1.Items.Add(s);
    progressBar1.Value += 1;
                }
                catch (ArgumentOutOfRangeException e)
                {
                }
            }
    13 ноября 2011 г. 6:45
  • я еще сделал с использованием пула потоков

    там все работает прекрасно - форма не зависает и можно прокрутывать listview 

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

    я пробовал создать 10 потоков и каждому назначить по 12000 портов но потоки с циклами работать не хотят 

    то есть они по 1 порту  выводят и все

    13 ноября 2011 г. 6:49
  • > я пробовал создать 10 потоков и каждому назначить по 12000 портов но потоки с циклами работать не хотят


    using System.Threading.Tasks;
    using System.Collections.Concurrent;
    ...
    Parallel.ForEach(Partitioner.Create(0, 65500, 12000), (range, state) =>
    {
        for (int i = range.Item1; i < range.Item2; i++)
        {
            ...
        }
    });
    

    • Помечено в качестве ответа lindstorm 13 ноября 2011 г. 21:33
    13 ноября 2011 г. 19:06
  • using System.ComponentModel;
    using System.Windows.Forms;
    using System.Threading.Tasks;
    using System.Net.Sockets;
    using System.Net;
    
    namespace WindowsFormsApplication136
    {
        public partial class Form1 : Form
        {
            int fromPort = 1;
            int toPort = 1000/*65535*/;
            int timeout = 200;
            int threads = 10;
            string host = "google.com";
    
            IPAddress remoteHost;
            ListView lv;
            ProgressBar pb;
            BackgroundWorker bw;
    
            public Form1()
            {
                lv = new ListView();
                lv.Parent = this;
                lv.Dock = DockStyle.Fill;
                lv.View = View.List;
    
                pb = new ProgressBar();
                pb.Parent = this;
                pb.Dock = DockStyle.Bottom;
                pb.Maximum = toPort  - fromPort + 1;
    
                remoteHost = Dns.Resolve(host).AddressList[0];
    
                bw = new BackgroundWorker();
                bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                bw.RunWorkerAsync();
                bw.WorkerReportsProgress = true;
                bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            }
    
            void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                pb.Value = e.ProgressPercentage;
                Text = "Processed " + e.ProgressPercentage + " ports";
            }
    
            void bw_DoWork(object sender, DoWorkEventArgs e)
            {
                int counter = 0;
                ParallelOptions po = new ParallelOptions();
                po.MaxDegreeOfParallelism = threads;
    
                Parallel.For(fromPort, toPort + 1, po, (port) =>
                    {
                        Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                        var res = socket.BeginConnect(remoteHost, port, null, socket);
                        res.AsyncWaitHandle.WaitOne(timeout, true);
                        Invoke(new MethodInvoker(() => OnPortIsAccessible(port, socket.Connected)));
                        if (socket.Connected)
                            socket.Close();
                        lock(bw) counter++;
                        bw.ReportProgress(counter);
                    }
                );
                Invoke(new MethodInvoker(() => Text = "Scanning is completed."));
            }
    
            void OnPortIsAccessible(int port, bool isAccessible)
            {
                if (isAccessible)
                    lv.Items.Add("Port " + port + " is accessible");
            }
        }
    }
    
    

    • Помечено в качестве ответа lindstorm 13 ноября 2011 г. 21:34
    13 ноября 2011 г. 20:10
  • Спасибо большое!

    Дай Бог тебе здоровья

    14 ноября 2011 г. 0:02