Reputation: 1068
I have a tool that does a port scan, the problem I am running into is that when the endpoint is unreachable the GUI freezes till it gets some sort of error. I have tried creating a thread but I am not too familiar with how to do it. Can someone show me how?
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)
{
}
}
}
Upvotes: 0
Views: 293
Reputation: 16209
The first problem, is that Socket.Connect()
is a blocking method. It'll not return until the connection succeeded/refused. You can use the asynchronous methods instead BeginConnect()
and EndConnect()
. But this is not the real problem, because you are already using a new thread.
The second problem, is that you can't update your GUI from an other thread than the main thread.
Invoke(new MethodInvoker(() =>
{
... // GUI updates (like your resultsTextBox)
}));
If you do not like the Invoke
stuff, you can use a BackgroundWorker
and its ReportProgress
method + ProgressChanged
event.
And @Hmm is right, since you do not use a new Thread
object, the method is called on the GUI thread. But you need to Invoke
updates then, as I described above.
EDIT
Btw, the cleanest solution would be to use AOP (OnGuiThreadAttribute
) in order to fulfill seperation of concerns.
Upvotes: 1
Reputation: 2282
private void button1_Click(object sender, EventArgs e)
{
ThreadStart threadStart = GetPortStatus;
threadStart.BeginInvoke(null, null);
GetPortStatus();
}
Should be:
private void button1_Click(object sender, EventArgs e)
{
ThreadStart threadStart = new ThreadStart(GetPortStatus);
Thread name = new Thread(threadStart);
name.Start();
}
You pass a delegate of the function you wish to invoke in the threadstart constructor. Threadstart represents a method that executes on a thread.
Upvotes: 1
Reputation: 1020
If you are building a Windows Forms application that needs to perform tasks on a separate thread, I would recommend you use the BackgroundWorker
component. There is an excellent tutorial on how to use this component at http://www.dotnetperls.com/backgroundworker.
Upvotes: 1