Is it possible to check an Idle Application from another application? [duplicate] - c#

This question already has answers here:
How to check if process is idle? C#
(2 answers)
Closed 4 years ago.
I have several programs that are already released. I want to create new program to read the released running programs - wheather they are idle or not for about 5 minutes. If they are in the idle condition, I want to terminate them.
IDLE means the user not use mouse and keyboard or no process in that program.
As an example, these are my several released programs:
pgrA.exe - Running - Idle 3 Minutes
pgrB.exe - Stopped
pgrC.exe - Running - Idle 7 Minutes
pgrD.exe - Running - not Idle
pgrE.exe - Running - Idle 11 Minutes
My program to terminate idle programs (on single PC):
IdleReader.exe (will terminate pgrC.exe and pgrE.exe)
that all running in 1 PC.
this some codes of the new program to terminate idle Program:
private void refresh_PrgList()
{
using (var con = new SqlConnection(ConfigurationManager.AppSettings["ConnectionStr"]))
using (var cmd = con.CreateCommand())
{
con.Open();
cmd.CommandText = "select ProgramID, ProgramName from MKTPrograms";
var reader = cmd.ExecuteReader();
var yy = false;
dgvPrgList.Rows.Clear();
while (reader.Read())
{
yy = false;
foreach (var xx in Process.GetProcesses())
if (xx.ProcessName.Replace(".exe", string.Empty).ToUpper() == reader[0].ToString().Replace(" ", string.Empty).ToUpper())
{
//----- I want to Detect the Idle Program here -----//
//--------------------------------------------------//
dgvPrgList.Rows.Add(new object[] { reader[0].ToString(), reader[0].ToString(), "Running", xx.StartTime, System.DateTime.Now - xx.StartTime });
yy = true;
}
if (yy == false)
dgvPrgList.Rows.Add(new object[] { reader[0].ToString(), reader[1].ToString(), "Stopped", "" });
}
for (int x = 1 ; x < dgvPrgList.Columns.Count ; x++ )
{
dgvPrgList.Columns[x-1].AutoSizeMode = DataGridViewAutoSizeColumnMode.DisplayedCells;
}
}
}
Thanks,

Sure, there are tons of ways to do that.
Look at the processing time (UserProcessorTime,TotalProcessorTime), store it and compare it; you'd get a good feeling about "idle" after some time.
Then just call Kill on the System.Diagnostics.Process class to terminate it.
In .net one can do:
var processName= "yourApp";
if (Process.GetProcessesByName(processName) == null)
Assert.Inconclusive("Skipped: {processName} is not running");
The above code is a unit test, and it can be used to get a specific process, you can find the name you are looking for in your resource monitor:
To see if an application is installed one would simulate the call to start that application, you'd do that like this:
/// <summary>
/// Determines whether the specified application executable is installed.
/// </summary>
/// <param name="name">The command line name.</param>
/// <returns><c>true</c> if the specified name is installed; otherwise, <c>false</c>.</returns>
public static bool IsInstalled(string name)
{
using (var key = Registry.ClassesRoot.OpenSubKey($"{name}\\shell\\open\\command"))
return key != null;
}
One can check if an application is having the right state by looking at the main window. you do this by getting the process as shown before
what I do to see if the application has started but the user is still at his login is:
if (MyAppProcess.MainWindowTitle.Contains("Login"))
return true;
I use:
if (!TCP.IsListing(login.ServerName, login.Port))
Assert.Inconclusive($"Skipped: TWS not accepting connection port {login.Port}");
To see if a method is accepting connections without actually creating a connection, no all applications like it when you just open a socket port, some crash, some corrupt.
The code that does that is listed below, only works locally, you can't do this remote. I use the host as my servers have more than 1 IP and failing to listen will cause my application to fire up a fallback instance and update the DNS server. Easy to create an application failover cluster without having to have enterprise licenses for all your multi-socket multi-core servers ;-)
public static bool IsListing(string hostUri, int portNumber, int millisecondTimeOut=500)
{
try
{
var info = new ProcessStartInfo() {
Arguments = "-a -p TCP",
CreateNoWindow=false,
FileName="netstat",
WindowStyle= ProcessWindowStyle.Hidden,
UseShellExecute = false,
RedirectStandardOutput = true
};
using (var p = Process.Start(info))
using (StreamReader reader = p.StandardOutput)
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (line.Contains($":{portNumber}"))
{
return true;
}
}
}
return false;
}
catch (SocketException)
{
return false;
}
}
You can see if a host (remote or local) can be reached using a ping. You can do that using:
public static async Task<bool> IsOnline(string hostUri)
{
try
{
object token = Guid.NewGuid().ToString();
using (var p = new Ping())
{
var result= await p.SendPingAsync(hostNameOrAddress: hostUri, timeout: 1000);
return result.Status == IPStatus.Success;
}
}
catch (Exception)
{
return false;
}
}

Related

Get applocker status of .exe file

I have developed a launcher that updates/run our software in other companies enviroment. Most of the time the company approves the launcher but forgets about the actual application.
Currently im using Process.Start(procStart) to start the application, but that silently fails if applocker blocks the application.
So i was wondering if someone reliable way of detecting if applocker is active, and when it blocks my application( So i can provide a proper error message).
When the error happens my application seems idle to the user, a memory dump shows this:
Code note:
There is no exception handling or suppression of exceptions. If the launcher crashes i would expect to see it in the eventlog.
Added code:
private void StartzzzDesktop(int value)
{
var rel = Settings.zzzDesktopStore.GetReleaseInfo(Settings.ConnectionDetails.zzzDesktopID);
var proc = CreateProccess(rel);
if (proc == null)
{
Settings.LastError = zzzLauncherError.FatelErrorStartzzz;
Settings.EventManager.TriggerEvent(zzzDesktopStatus.FatalError);
return;
}
Logger.Log(EventLogEntryType.Information, $"Started zzz desktop and got PID {proc.Id} from {rel.GenerateExtrationPath()}");
Settings.EventManager.TriggerEventSync(zzzDesktopStatus.DeleteOldReleases);
Settings.EventManager.TriggerEvent(zzzDesktopStatus.ReleaseBackgroundWorkers);
GC.Collect();
var remoteStatus = new GetRemotezzzWebStatus();
while (!proc.HasExited)
{
Thread.Sleep(1000);
if(!remoteStatus.IsRemoteVersionCompatible())
{
proc.Kill();
Logger.Log(EventLogEntryType.Information, $"Detected that the remote website is no longer compatible with current runnign version, and we are killing desktop.");
}
}
if(proc.ExitCode != 0)
{
Settings.zzzDesktopStore.Delete(rel);
Logger.Log(EventLogEntryType.Warning, $"zzz exited with a none zero exit code ({proc.ExitCode}), the local cached installation will be deleted");
}
else
Logger.Log(EventLogEntryType.Information, $"zzz exited in a normal way with exitcode {proc.ExitCode}, running for {(DateTime.Now - proc.StartTime).ToString()} ");
CloseDown();
}
internal Process CreateProccess(zzzDesktopInfo release)
{
release = GetReleaseInfo(release.ID);
string pathzzzExe = Path.Combine(release.GenerateExtrationPath(), "zzz.exe");
var verifyStatus = UtilsVerifyFile.Verify(pathzzzExe);
if ( !File.Exists(pathzzzExe) || !verifyStatus.Verified)
{
Logger.Log(EventLogEntryType.Error, "Found zzz.exe in temp folder, but the certificate did not pass verification");
foreach (var logentry in verifyStatus.Logs)
Logger.Log(EventLogEntryType.Error, "Certificate verification log: " + logentry);
MarkDatabaseForPurge();
return null;
}
// Removed enterprise spesific code.
var procStart = new ProcessStartInfo();
procStart.FileName = pathzzzExe;
if (Settings.ConnectionDetails.zzzLoginToken != Guid.Empty )
{
procStart.Arguments = "/RefreshToken:" + Settings.ConnectionDetails.zzzLoginToken.ToString();
}
var process = Process.Start(procStart);
return process;
}

Serial port sometimes takes (exactly) 30 seconds to Open or Close, only connects once without manual RTS control

I'm having a very peculiar issue with the serial port class in C# (using .NET 4.5 as a target). Our application needs the ability to switch between (close then open another) serial COM ports which are all USB 1.1 virtual COM port devices. The problem I'm having has two symptoms that may be related. First, we can only connect to our device after having already read from it using another terminal emulator or similar application and even then only once. After one successful connection all other attempts after closing and re-opening the port will never receive data (DataReceivedEvent never fires). The only workaround I have found to this is to manually drive the RTS signal as shown below (even though every other serial library or emulation program requires no handshaking to talk to this device, including TerraTerm, Java, and PySerial).
Second, even then, while the port may be freely opened and closed successful, occasionally (1/30 ish) the Open() or Close() functions take precisely 30 seconds to finish (30008 ms measured via a diagnostic Stopwatch) where it would normally take a mere 5-8 ms. There seems to be no explanation for this. Any thoughts?
Measures already used to try eliminating or mitigating the problem:
Attempts to Open or Close the port are executed as separate tasks in the thread pool so that they can be terminated or aborted cleanly after a specified period of time if unsuccessful (I use 60 seconds for this value in testing)
I've added various time delays both short (100 ms) and extreme (5000 ms) in every conceivable place with no effect (between port close and reopen, between open and close, and between open/close and RTS true/false
Double triple and quadruple checked the designed port parameters for our USB serial device
I've looked at this article by bvoigt and this article by Zach Saw which both seem to suggest that there are deeply rooted issues with .NET SerialPort class. This has left me with the impression that a third party library might be the best option (there are some good candidates on NuGet). Ultimately this will be used as the serial port within a WPF application.
Before anyone asks, no, simply opening the port and leaving it open is not an option in our application and, frankly, this is something that works seamlessly 100% of the time with the same device from the same hosts with the same driver in other languages' standard serial implementations (see above).
Please see the simple exemplary application below which I have been using to successfully reproduce this problem. Any pointers in the right direction are greatly appreciated!!!
SerialTestApplication.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Diagnostics;
using System.Threading;
namespace SerialTestApplication
{
class Program
{
private SerialPort S = new SerialPort();
private bool S_active = false;
private int succeed = 0;
private int fail = 0;
static void Main(string[] args)
{
Program P = new Program();
System.Threading.Thread.Sleep(1000);
var test_timer = new Stopwatch();
test_timer.Start();
for (int a = 0; a < 100; a++)
{
P.ConnectSerial(P);
P.CloseSerial(P);
}
Console.WriteLine("EXIT");
System.Threading.Thread.Sleep(1000);
Console.ReadLine();
}
private bool ConnectSerial(Program P)
{
if (S.IsOpen)
{
fail++;
Console.WriteLine("PORT NOT CLOSED YET");
return false;
}
// Setup The Serial COMM Port
S.PortName = "COM1";
S.BaudRate = 115200;
S.Handshake = System.IO.Ports.Handshake.None;
S.Parity = Parity.None;
S.DataBits = 8;
S.StopBits = StopBits.One;
// Write Properties
S.WriteBufferSize = 2048;
S.WriteTimeout = 500;
// Read Properties
S.ReceivedBytesThreshold = 1;
S.ReadBufferSize = 2048;
S.ReadTimeout = 500;
try
{
S_active = false;
if (!P.OpenSerial(P))
{
fail++;
return false;
}
var connection_timer = new Stopwatch();
connection_timer.Start();
while (S.IsOpen && !S_active)
{
if (connection_timer.ElapsedMilliseconds > 1000)
{
fail++;
CloseSerial(this);
Console.WriteLine("Succeed/Fail: " + succeed + " " + fail);
return false;
}
}
succeed++;
Console.WriteLine("Succeed/Fail: " + succeed + " " + fail);
Console.WriteLine(S.BytesToWrite + " " + S.BytesToRead);
return true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
private void Receive(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (S.IsOpen)
{
S_active = true;
S.ReadExisting();
}
}
private bool OpenSerial(Program P)
{
Task OpenAttempt = Task.Factory.StartNew(() =>
{
try
{
if (S.IsOpen)
{
Console.WriteLine("PORT STILL OPEN!");
return;
}
S.Open();
S.DiscardInBuffer();
S.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Receive);
S.RtsEnable = true;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
});
var open_timer = new Stopwatch();
open_timer.Start();
OpenAttempt.Wait(60000);
Console.WriteLine("Opened In: " + open_timer.ElapsedMilliseconds);
return S.IsOpen;
}
private void CloseSerial(Program P)
{
Task CloseAttempt = Task.Factory.StartNew(() =>
{
try
{
S.RtsEnable = false;
S.Close();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
});
var close_timer = new Stopwatch();
close_timer.Start();
CloseAttempt.Wait(60000);
Console.WriteLine("Closed In: " + close_timer.ElapsedMilliseconds);
}
}
}
EDIT 1
I've found one issue with this but unfortunately it doesn't solve the core "takes 30 seconds to finish the Open() or Close() method" problem. The way I am recycling (closing and reopening) the SerialPort object in this test application adds a new DataReceived event handler every time the port is reopened. Basically after closing/opening the port 10 times there will be ten DataReceived handlers associated with the object. To correct that I'm now letting Close() Dispose() the SerialPort object then setting the reference to null and creating a completely new instance of SerialPort on the next open. That seems to ensure that the serial port is properly released so long as the USB cable is not physically pulled out of the computer.

running multiple threads with continous value returns (ping program)

good day
I have taken up a project that as a bases needs insernt a command into cmd "ping x.x.x.x -t" and the program needs to return the output until a specified parameter
I am considering threads as my unterstanding in multithreading is limited, I am unable to continue without guidance
my ping class which recieves a string ip, adds it to a precompiled command string, etc.
I am aware of the built in ping class for this use, but I would prefer the "longer" method since i would gain valueble information/experience from this
main object class: ping
class ping
{
Process proc;
ProcessStartInfo psi;
string ip_address;
bool bStop = false;
public ping(string ip)
{
ip_address = ip;
}
public void StartPing()
{
string cmdInput;
psi = new ProcessStartInfo(Environment.GetEnvironmentVariable("COMSPEC"));
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
proc = Process.Start(psi);
proc.StandardInput.WriteLine("ping " + ip_address + " -t");
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
cmdInput = proc.StandardOutput.ReadLine();
while (bStop == false)
{
cmdInput = proc.StandardOutput.ReadLine();
Console.WriteLine(returnPing(cmdInput));
}
proc.Close();
}
private string returnPing(string cmdInput)
{
int start, end;
string ping;
if (cmdInput.IndexOf("Reply") != -1 && cmdInput.IndexOf("time") != -1)
{
start = cmdInput.IndexOf("time=") + 5;
end = cmdInput.IndexOf("ms");
ping = cmdInput.Substring(start, end - start);
return ping;
}
else return "-1";
}
and thread_handler class, which manages mutliple instances of the ping method, please not the console.writeline is a temporary output which I will change in the future
class thread_handler
{
string[] ipList;
private IList<Thread> threadList;
public thread_handler(string[] ip)
{
ipList = ip;
threadList = new List<Thread>();
createThreads();
}
private void createThreads()
{
foreach (string item in ipList)
{
ping NewPing = new ping(item);
Thread newPingThread = new Thread(NewPing.StartPing);
newPingThread.IsBackground = true;
newPingThread.Name = string.Format("{0}", item);
threadList.Add(newPingThread);
}
startAllThreads();
}
private void startAllThreads()
{
foreach (Thread item in threadList)
{
item.Start();
}
}
}
Program
class Program
{
static string[] ipList;
static void Main(string[] args)
{
ipList = new String[3];
readData();
sendData();
}
private static void sendData()
{
thread_handler thIp = new thread_handler(ipList);
}
private static void readData()
{
//use sll with name defintions and ip address's with metadata
ipList[0] = "10.0.0.2";
ipList[1] = "telkom_exchange";
ipList[2] = "goo.gl";
}
The aim of this program is (with gui changes in future) for a simple console with respective dimensions to constantly ping certain ip address's (we have ban infrastructure, thus program is for informative purposes), constantly updating on every ping reply
I do not want anyone to finish this program, I simply require assistance with running multiple instances (or maybe "threads") of this pinging, thus
each thread as it runs the "StartPing()" method, it should return an output, e.g. simply output the ping into the console, but it doesnt...
Output:
The process tried to write to a nonexistent pipe.
The process tried to write to a nonexistent pipe.
then hangs
The way you read from the child process is not right. This is a surprisingly complicated task. I don't know why you are getting this specific error message but it sounds like it has to do with process standard output redirection. For example you have not redirected standard error.
I suggest you use one of the top voted snippets of stack overflow, to be found by: site:stackoverflow.com process RedirectStandardOutput. There are hundreds of such questions. Most solutions are subtly wrong.
This is a good checklist.
You should use the ping class to execute a ping. This class allows you to control many details.
The call to ping.exe with Process.Start() involves way too much overhead and complicates things (as you experienced in your try)
As simple as it is, redirecting standard input and output did it, with a tweak or two, voila

How to kill only processes started by my application

I am using Selenium WebDriver in an application and I have code to kill the webdrivers and browser instances. However, I am thinking that if the user had any IE browsers open before running the application that this code will kill not only the IE processes spawned by my application but also the IE instances that user had open prior to running the application.
Is there a way to track the processes started by my application so I can filter this method to kill only IE processes spawned by my application, or determine that IE driver and browser instance was spawned by my application, or perhaps both?
public void KillAllBrowsersAndWebDrivers()
{
var webDrivers = Process.GetProcessesByName("IEDriverServer").Select(p => p.Id);
var browsers = Process.GetProcessesByName("iexplore").Select(p => p.Id);
var processIds = webDrivers.Concat(browsers);
// do some stuff with PID, if you want to kill them, do the following
foreach (var pid in processIds)
{
try
{
Process.GetProcessById(pid).Kill();
Logger.Log(Loglevel.Debug, "Kill Process:{0}", pid);
}
catch (Exception)
{
Logger.Log(Loglevel.Error, "Error killing process: {0}", pid);
}
}
}
All you would have to do is keep a list of all the processes you've created.
this is a very simple process manager. This code is error prone, and there is no exception handling
private static List<Process> processes = new List<Process>();
static void Main(string[] args)
{
int PID = StoreProcess (yourProcess);
KillProcess(PID);
}
/// <summary>
/// Stores the process in a list
/// </summary>
/// <returns>The PID</returns>
/// <param name="prc">The process to be stored</param>
public static int StoreProcess(Process prc)
{
int PID = prc.Id; // Get the process PID and store it in an int called PID
processes.Add (prc); // Add this to our list of processes to be kept track of
return PID; // Return the PID so that the process can be killed/changed at a later time
}
/// <summary>
/// Kills a process
/// </summary>
/// <param name="PID">The PID of the process to be killed.</param>
public static void KillProcess(int PID)
{
// Search through the countless processes we have and try and find our process
for (int i = 0; i <= processes.Count; i++) {
if (processes [i] == null)
{
continue; // This segment of code prevents NullPointerExceptions by checking if the process is null before doing anything with it
}
if (processes [i].Id == PID) { // Is this our process?
processes [i].Kill (); // It is! Lets kill it
while (!processes [i].HasExited) { } // Wait until the process exits
processes [i] = null; // Mark this process to be skipped the next time around
return;
}
}
// Couldn't find our process!!!
throw new Exception ("Process not found!");
}
Advantages:
You can keep track of all the processes you've initialized, and terminate them one by one at any time
Drawbacks:
I don't believe there is any
Another possible solution is to get a list of the processes running BEFORE spawning any new processes. Then just kill the ones that are not in the list of previously running processes.
public void KillOnlyProcessesSpawnedBySelenium()
{
// get a list of the internet explorer processes running before spawning new processes
var pidsBefore = Process.GetProcessesByName("iexplore").Select(p => p.Id).ToList();
var driver = new Driver(Settings);
var driver1 = driver.InitiateDriver(); // this method creates new InternetExplorerDriver
var driver2 = driver.InitiateDriver();
var driver3 = driver.InitiateDriver();
driver1.Navigate().GoToUrl("http://google.com");
driver2.Navigate().GoToUrl("http://yahoo.com");
driver3.Navigate().GoToUrl("http://bing.com");
var pidsAfter = Process.GetProcessesByName("iexplore").Select(p => p.Id);
var newInternetExplorerPids = pidsAfter.Except(pidsBefore);
// do some stuff with PID, if you want to kill them, do the following
foreach (var pid in newInternetExplorerPids)
{
Debug.WriteLine("Killing pid: {0}", pid);
Process.GetProcessById(pid).Kill();
}
Assert.IsTrue(pidsBefore.Count > 0);
// determine if each process before the drivers spawned are running
foreach (var running in pidsBefore.Select(pid => Process.GetProcessById(pid).IsRunning()))
{
Assert.IsTrue(running);
}
}
Here is an extension method to use to determine if a process is still running or not...
public static bool IsRunning(this Process process)
{
if (process == null)
throw new ArgumentNullException("process");
try
{
Process.GetProcessById(process.Id);
}
catch (ArgumentException)
{
return false;
}
return true;
}

HttpWebRequest Limitations? Or bad implementation

I am trying to build a c# console app that will monitor about 3000 urls (Just need to know that HEAD request returned 200, not necessarily content, etc.)
My attempt here was to build a routine the checks the web URLS, looping and creating threads each executing the routine. What's happening is if i run with <20 threads, it executes ok most of the time, but if i use >20 threads, some of the url's time out. I tried increasing the Timeout to 30 seconds, same occurs. The network I am running this on is more than capable of executing 50 HTTP HEAD requests (10MBIT connection at ISP), and both the CPU and network run very low when executing the routine.
When a timeout occurs, i test the same IP on a browser and it works fine, I tested this repeatedly and there was never a case during testing that a "timed out" url was actually timing out.
The reason i want to run >20 threads is that i want to perform this test every 5 minutes, with some of the URL's taking a full 10sec (or higher if the timeout is set higher), i want to make sure that its able to run through all URLs within 2-3 minutes.
Is there a better way to go about checking if a URL is available, or, should I be looking at the system/network for an issue.
MAIN
while (rdr.Read())
{
Thread t = new Thread(new ParameterizedThreadStart(check_web));
t.Start(rdr[0]);
}
static void check_web(object weburl)
{
bool isok;
isok = ConnectionAvailable(weburl.ToString());
}
public static bool ConnectionAvailable(string strServer)
{
try
{
strServer = "http://" + strServer;
HttpWebRequest reqFP = (HttpWebRequest)HttpWebRequest.Create(strServer);
reqFP.Timeout = 10000;
reqFP.Method = "HEAD";
HttpWebResponse rspFP = (HttpWebResponse)reqFP.GetResponse();
if (HttpStatusCode.OK == rspFP.StatusCode)
{
Console.WriteLine(strServer + " - OK");
rspFP.Close();
return true;
}
else
{
Console.WriteLine(strServer + " Server returned error..");
rspFP.Close();
return false;
}
}
catch (WebException x)
{
if (x.ToString().Contains("timed out"))
{
Console.WriteLine(strServer + " - Timed out");
}
else
{
Console.WriteLine(x.Message.ToString());
}
return false;
}
}
Just remember, you asked.
Very bad implementation.
Do not go creating threads like that. It does very little good to have more threads than processor cores. The extra threads will pretty much just compete with each other, especially since they're all running the same code.
You need to implement using blocks. If you throw an exception (and chances are you will), then you will be leaking resources.
What is the purpose in returning a bool? Do you check it somewhere? In any case, your error and exception processing are a mess.
When you get a non-200 response, you don't display the error code.
You're comparing against the Message property to decide if it's a timeout. Microsoft should put a space between the "time" and "out" just to spite you.
When it's not a timeout, you display only the Message property, not the entire exception, and the Message property is already a string and doesn't need you to call ToString() on it.
Next Batch of Changes
This isn't finished, I don't think, but try this one:
public static void Main()
{
// Don't mind the interpretation. I needed an excuse to define "rdr"
using (var conn = new SqlConnection())
{
conn.Open();
using (var cmd = new SqlCommand("SELECT Url FROM UrlsToCheck", conn))
{
using (var rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
// Use the thread pool. Please.
ThreadPool.QueueUserWorkItem(
delegate(object weburl)
{
// I invented a reason for you to return bool
if (!ConnectionAvailable(weburl.ToString()))
{
// Console would be getting pretty busy with all
// those threads
Debug.WriteLine(
String.Format(
"{0} was not available",
weburl));
}
},
rdr[0]);
}
}
}
}
}
public static bool ConnectionAvailable(string strServer)
{
try
{
strServer = "http://" + strServer;
var reqFp = (HttpWebRequest)WebRequest.Create(strServer);
reqFp.Timeout = 10000;
reqFp.Method = "HEAD";
// BTW, what's an "FP"?
using (var rspFp = (HttpWebResponse) reqFp.GetResponse()) // IDisposable
{
if (HttpStatusCode.OK == rspFp.StatusCode)
{
Debug.WriteLine(string.Format("{0} - OK", strServer));
return true; // Dispose called when using is exited
}
// Include the error because it's nice to know these things
Debug.WriteLine(String.Format(
"{0} Server returned error: {1}",
strServer, rspFp.StatusCode));
return false;
}
}
catch (WebException x)
{
// Don't tempt fate and don't let programs read human-readable messages
if (x.Status == WebExceptionStatus.Timeout)
{
Debug.WriteLine(string.Format("{0} - Timed out", strServer));
}
else
{
// The FULL exception, please
Debug.WriteLine(x.ToString());
}
return false;
}
}
Almost Done - Not Tested Late Night Code
public static void Main()
{
using (var conn = new SqlConnection())
{
conn.Open();
using (var cmd = new SqlCommand("", conn))
{
using (var rdr = cmd.ExecuteReader())
{
if (rdr == null)
{
return;
}
while (rdr.Read())
{
ThreadPool.QueueUserWorkItem(
CheckConnectionAvailable, rdr[0]);
}
}
}
}
}
private static void CheckConnectionAvailable(object weburl)
{
try
{
// If this works, it's a lot simpler
var strServer = new Uri("http://" + weburl);
using (var client = new WebClient())
{
client.UploadDataCompleted += ClientOnUploadDataCompleted;
client.UploadDataAsync(
strServer, "HEAD", new byte[] {}, strServer);
}
}
catch (WebException x)
{
Debug.WriteLine(x);
}
}
private static void ClientOnUploadDataCompleted(
object sender, UploadDataCompletedEventArgs args)
{
if (args.Error == null)
{
Debug.WriteLine(string.Format("{0} - OK", args.UserState));
}
else
{
Debug.WriteLine(string.Format("{0} - Error", args.Error));
}
}
Use ThreadPool class. Don't spawn hundreds of threads like this. Threads have such a huge overhead and what happens in your case is that your CPU will spend 99% time on context switching and 1% doing real work.
Don't use threads.
Asynch Call backs and queues. Why create a thread when the resource that they are all wanting is access to the outside world. Limit your threads to about 5, and then implement a class that uses a queue. split the code into two parts, the fetch and the process. One controls the flow of data while the other controls access to the outside world.
Use whatever language you like but you won't got wrong if you think that threads are for processing and number crunching and async call backs are for resource management.

Categories