Think We have this part in our program:
private void button1_Click(object sender, EventArgs e)
{
while (true) ;
}
If we run the program it will crash and say "Not Responding". How to prevent this. I want the program check itself and if it dose not respond, restart itself.
Note:
We can use BackgroundWorker class. like this:
private readonly BackgroundWorker worker;
public Form1()
{
InitializeComponent();
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += Form1_Load;
worker.ProgressChanged += button1_Click;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
}
But there is no method or property or event in that class to understand not responding.
Any help will be appreciate.
Edit 3:
I used BackgroundWorker with ThredTimer and checked if process is "Not Responding". This dose not close the program but start a new one.
Certainly this is not a clean code, but it is a way. I'm still looking for how to use BeginInvoke as @micky said Or other way to make this beautiful. Thanks to all of you
private readonly BackgroundWorker _Worker;
public Form1()
{
InitializeComponent();
_Worker = new BackgroundWorker();
_Worker.DoWork += new DoWorkEventHandler(_Worker_DoWork);
_Worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_Worker_RunWorkerCompleted);
_Worker.WorkerReportsProgress = true;
_Worker.WorkerSupportsCancellation = true;
}
// BCW starts here.
private void button1_Click(object sender, EventArgs e)
{
_Worker.RunWorkerAsync();
while (true) ;
}
// ThreadTimer will run here.
void _Worker_DoWork(object sender, DoWorkEventArgs e)
{
if (_Worker.IsBusy == true)
{
if (_Worker.CancellationPending)
{
e.Cancel = true;
}
TimerCallback tmrCallBack = new TimerCallback(CheckStatusThreadHealth);
System.Threading.Timer tmr = new System.Threading.Timer(tmrCallBack, null, 10000, 10000);
}
}
// This will call by ThreadTimer and check processes for not responding
public void CheckStatusThreadHealth(object IsBusy)
{
Process application = null;
foreach (var process in Process.GetProcesses())
{
if (process.ProcessName == "WindowsFormsApplication1")
{
application = process;
break;
}
}
if (!application.Responding)
{
// This should end BCW and go to _Worker_RunWorkerCompleted. But it didn't
_Worker.CancelAsync();
// This Restart program but did not close the last one.
Application.Restart();
}
}
// this should run when BCW has error or cancel, But never this happen
void _Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Application.Restart();
return;
}
}
The Answer: Thanks to Jason Williams
I used a watch dog program as a solution and Communicate between two program by this link The code Changed to this:
In Main Program
public partial class Form1 : Form
{
// Use SendMessage API
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SendMessage(IntPtr hwnd, uint Msg, IntPtr wParam, IntPtr lParam);
// define a message
private const int RF_TESTMESSAGE = 0xA123;
// The timer will begin with the form
public Form1()
{
InitializeComponent();
var timer = new Timer();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 10000; //10 seconds
timer.Start();
}
//Timer look for a Watch Dog Program and send message to it
void timer_Tick(object sender, EventArgs e)
{
try
{
Process WatchDogProccess = Process.GetProcessesByName("Watch Dog")[0];
SendMessage(WatchDogProccess.MainWindowHandle, RF_TESTMESSAGE, IntPtr.Zero, IntPtr.Zero);
}
catch
{
//if Watch Dog is not running, will reach here
}
}
// if we click this button we will got "Not Responding"
private void button1_Click(object sender, EventArgs e)
{
while (true) ;
}
}
In Watch Dog Program
public partial class Form2 : Form
{
//the message that have been define in main program
private const int RF_TESTMESSAGE = 0xA123;
//Recive the message
protected override void WndProc(ref Message message)
{
if (message.Msg == RF_TESTMESSAGE)
{
// this mean the mian program run perfectly
}
else
{
//the main program is not responding
//Main program's name and address
string FileAddress = @"C:\Users\...\MainProgram.exe";
string FileName = "MainProgram";
// This will restart the main program
RestartProgram(FileAddress, FileName);
}
base.WndProc(ref message);
}
// This will restart the main program
public void RestartProgram(string FileAddress, string FileName)
{
//Find the Process
Process[] prs = Process.GetProcessesByName(FileName);
foreach (Process pr in prs)
{
if (!pr.Responding)
{
try
{
pr.Kill();
//then to restart-
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = FileAddress
}
};
process.Start();
}
catch { }
}
}
}
public Form2()
{
InitializeComponent();
}
}
}