Потоки в GUI - PullRequest
       24

Потоки в GUI

0 голосов
/ 23 декабря 2011

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

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace PortScan
{
    public partial class Form1 : Form
    {


        public Form1()
        {
            InitializeComponent();
            timeTextBox.Text = "2000";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ThreadStart threadStart = GetPortStatus;
            threadStart.BeginInvoke(null, null);
            GetPortStatus();
        }

        private void GetPortStatus()
        {
            button1.Enabled = false;
            var currentIP = ipaddressTextBox.Text;
            int anInteger;
            anInteger = Convert.ToInt32(portTextBox.Text);
            anInteger = int.Parse(portTextBox.Text);

            IPAddress IP = IPAddress.Parse(currentIP);
            IPEndPoint EndPoint = new IPEndPoint(IP, anInteger);

            Socket query = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            //Console.WriteLine("Blocking: {0}", query.Blocking);

            //resultsTextBox.Text = currentIP + ":" + anInteger + " is blocked: " + query.Blocking;
            //resultsTextBox.Text += Environment.NewLine + currentIP + ":" + anInteger + " is blocked: " + query.Blocking;
            try
            {
                query.Connect(EndPoint);
                resultsTextBox.Text += "Connected to " + EndPoint + Environment.NewLine;
            }
            catch (SocketException i)
            {
                //Console.WriteLine("Problem connecting to host");
                //Console.WriteLine(e.ToString());
                resultsTextBox.Text += "Cannot connect to " + EndPoint + ", port maybe blocked" + Environment.NewLine;
                query.Close();
                button1.Enabled = true;
                return;
            }
            //if (InvokeRequired)
            //{
            //    Invoke(new MethodInvoker(Close));
            //}
            //else
            //{
            //    Close();
            //}

            query.Close();
            button1.Enabled = true;
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (autoCheckBox.Checked == true)
            {
                button1_Click(sender, e);
            }
            else
            {
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }
    }
}

Ответы [ 3 ]

1 голос
/ 23 декабря 2011

Первая проблема заключается в том, что Socket.Connect() является методом блокировки. Он не вернется, пока соединение не установится / не будет отказано. Вы можете использовать асинхронные методы вместо BeginConnect() и EndConnect(). Но это не настоящая проблема, потому что вы уже используете новый поток.

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

        Invoke(new MethodInvoker(() =>
        {
               ... // GUI updates (like your resultsTextBox)
        }));

Если вам не нравится материал Invoke, вы можете использовать BackgroundWorker и его ReportProgress метод + ProgressChanged событие.

И @Hmm прав, поскольку вы не используете новый объект Thread, метод вызывается в потоке GUI. Но тогда вам нужно Invoke обновления, как я описал выше.

EDIT

Кстати, самым чистым решением было бы использование AOP (OnGuiThreadAttribute) для выполнения разделения проблем .

1 голос
/ 23 декабря 2011

Если вы создаете приложение Windows Forms, которое должно выполнять задачи в отдельном потоке, я бы порекомендовал вам использовать компонент BackgroundWorker.На http://www.dotnetperls.com/backgroundworker.

есть отличное руководство по использованию этого компонента.
1 голос
/ 23 декабря 2011
    private void button1_Click(object sender, EventArgs e)
    {
        ThreadStart threadStart = GetPortStatus;
        threadStart.BeginInvoke(null, null);
        GetPortStatus();
    }

Должно быть:

    private void button1_Click(object sender, EventArgs e)
    {
        ThreadStart threadStart = new ThreadStart(GetPortStatus);
        Thread name = new Thread(threadStart);
        name.Start();
    }

Вы передаете делегат функции, которую хотите вызвать, в конструкторе запуска потока. Threadstart представляет метод, который выполняется в потоке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...