My questions is a bit generic, because I'm still trying to understand how to correctly implement that, however, given I have this code:
class Class1
{
public static void Something()
{
if (a)
{
//do something in a;
if (b)
{
//do something in b;
if (c)
{
//do something in c;
if (d)
{
while (Process.GetProcessesByName("ProcessName").Length > 0)
{
//execute action
return;
}
if (Process.GetProcessesByName("ProcessName").Length <= 0)
{
//execute action when the ProcessName is closed
...
//start the loop from beginning
Something();
}
}
}
}
}
}
}
What I want to achieve is:
Loop starts with Something(), until it reaches the if (d) condition, then I want to run certain actions in loop until a given process name is running, maybe using a new thread for performance(?). Once the process name is not found anymore, I want to do some other actions, and then start again from the beginning. Is that possible?
What would be the best way to achieve that?
Not sure if this is quite what you're after...but it ~might~ be a good start?
class Class1
{
private static bool a=true, b=true, c=true;
private static bool d()
{
Console.WriteLine("Launching Notepad");
Process P = Process.Start("notepad");
Console.WriteLine("Waiting for Notepad");
P.WaitForInputIdle();
Console.WriteLine("Notepad is ready!");
return true;
}
public static void Something()
{
while (true) // not sure how/when this exits
{
if (a)
{
//do something in a;
if (b)
{
//do something in b;
if (c)
{
//do something in c;
if (d())
{
// we'll assume after "d", the process has started
Process P = Process.GetProcessesByName("notepad").FirstOrDefault();
if (P != null)
{
P.EnableRaisingEvents = true;
P.Exited += (s, e) => {
//execute action when the ProcessName is closed
Console.WriteLine("Notepad closed.");
};
// execute action here?
Console.WriteLine("Action before loop.");
int counter = 1;
while (!P.HasExited)
{
// execute action or here?
Console.WriteLine("Waiting for Notepad to close: " + counter.ToString());
System.Threading.Thread.Sleep(1000); // check every second?
counter++;
}
}
}
}
}
}
}
}
}
Is this running in a WinForms app? Console app? Something else?...
Related
I have been trying to work out why my background worker is 'finishing' its work when there is still a lot for it to do. I am actually in the process of refactoring the code for this app, so it did work in the past, but now I am unable to figure out what has gone wrong.
Specifically, the app should open Outlook and then perform a few checks. However, the background worker exits straight after Outlook is opened for no apparent reason (as you will se below there is still plenty of processing to be done).
This appears to be happening early on in the Start() method, directly after calling Process.Start() on Outlook.exe.
The code runs in this order:
calling the background worker - this was the user's choice from a radio set
....
else if (radioButton5.Checked == true)
{
textBox1.Text = "Please wait while your session restarts";
pageControl1.SelectedIndex = 10;
backgroundReset.RunWorkerAsync();
}
The do-work method
public void backgroundReset_DoWork(object sender, DoWorkEventArgs e)
{
backgroundReset.WorkerSupportsCancellation = true;
Session.Reset();
}
the reset session method starts by killing the current session ...
public static void Reset()
{
KillSession();
System.Threading.Thread.Sleep(5000);
Start();
// THE BACKGROUNDWORKER EXITS BEFORE HERE!
if (IsLoggedIn() == false)
{
return;
}
else
{
// Make sure Lync is open before finishing the process ...
var j = 0;
GetSession(Init.servers);
j = 0;
var checker = false;
checker = ProcessHandler.CheckRunning("lync.exe");
while (checker == false)
{
if (j == 100)
{
break;
}
Thread.Sleep(500);
checker = ProcessHandler.CheckRunning("lync.exe");
j++;
}
}
}
As you can see from the comment, the backgroundworder is calling RunWorkerCompleted way before the Reset() method has finished executing.
Below are the other methods called (kill, logoff, start):
KillSession logs the session of and then makes sure it is logged off
private static void KillSession()
{
if (sessionId != null)
{
LogOff();
for (int i = 0; i < 150; i++)
{
if (IsLoggedIn() == true)
{
Thread.Sleep(500);
}
else
{
break;
}
}
}
}
LogOff sends a Cmd command to log off the current session
public static void LogOff()
{
string strCmdIn = "/C LOGOFF " + sessionId + " /SERVER:" + serverName;
Cmd.Exec(strCmdIn);
}
Start() Simply opens Outlook, causing a Citrix session to also start. The app is definitely launching Outlook, but after that it doesn't reach either of the for statements - the BackgroundWorker just exits.
public static void Start()
{
Process.Start(appDataCitrix + "Outlook.exe");
for (int i = 0; i < 15; i++)
{
if (IsLoggedIn2() == false)
{
Thread.Sleep(1000);
}
else
{
break;
}
}
if (IsLoggedIn2() == false)
{
Process.Start(appDataCitrix + "Outlook.exe");
for (int i = 0; i < 10; i++)
{
if (IsLoggedIn2() == false)
{
Thread.Sleep(1000);
}
else
{
break;
}
}
}
}
Does anyone have any idea what is going on here? It is driving me crazy!
Many thanks
Update
The RunWorkerCompleted Method:
As far as my understanding goes, this has no baring on when the process will finish.
public void backgroundReset_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (Session.IsLoggedIn())
{
btnFailFinish.Visible = true;
label10.Text = Session.serverName;
pageControl1.SelectedIndex = 3;
}
else
{
pageControl1.SelectedIndex = 10;
pictureBox2.Visible = false;
textBox1.Text = "Double-click Outlook on your desktop to launch a new session.";
textBox15.Text = "Once you have done this please click Finish.";
pictureBox9.Visible = true;
}
}
This is probably because of an exception being thrown from within the start method.
You may either add a try / catch block all around this method and handle the error from within the catch, or check in the RunWorkerCompleted method if an exception occurred :
private void RunWorkerCompleted (object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
// handle your exception here
}
}
I have a probably simple question about the task factory. I have to following code:
In this task is a loop that is polling data from the RS232 and a counter that stops polling after 10 times. After this "doCollect" will be set to false.
And now comes the strange thing: The task runs repeatedly. The caller code is:
// class Main()
RS232DataAquisition _RS232DataAquisition = new RS232DataAquisition();
public override void Run()
{
System.Diagnostics.Stopwatch timeout = new System.Diagnostics.Stopwatch();
timeout.Start();
_RS232DataAquisition.Start();
while ((timeout.ElapsedMilliseconds <= (dataGatherTime_inSeconds * 1000)) && _RS232DataAquisition.DoCollect)
{
System.Threading.Thread.Sleep(100);
}
timeout.Stop();
_RS232DataAquisition.Stop();
}
Per my understanding the Run() function should start the thread and return into the while-loop waiting for the thread to finish. But it never does?!
Here's the code for ReadDataFromRS232:
// sealed class RS232DataAquisition
private bool doCollect = false;
public bool DoCollect
{
get { return doCollect; }
}
public void Start()
{
doCollect = true;
currentTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
this.ReadDataFromRS232();
});
}
private void ReadDataFromRS232(int NumtoRead = 10)
{
var port = new System.IO.Ports.SerialPort(PortName);
int waitCount = 5;
var portExists = System.IO.Ports.SerialPort.GetPortNames().Any(x => x == PortName);
if (!portExists)
{
throw new ArgumentException("Port does not exist!");
}
while (port.IsOpen && waitCount-- > 0)
{
doCollect = false;
Wait();
}
doCollect = true;
if (!port.IsOpen)
{
port.Open();
port.NewLine = _NewLine;
port.ReadTimeout = 2000;
int number;
try { }
finally { }
port.Write("flashon\r");
while (doCollect && (_readCounter <= NumtoRead))
{
string s;
try
{
s = port.ReadLine();
}
catch
{
s = "-1";
}
int i;
if (int.TryParse(s, out i))
{
number = Convert.ToInt32(s, 10);
}
else
{
number = 0;
}
lock (thisLock) _data.Add(number);
_readCounter++;
}
port.Write("flashoff\r");
port.Close();
port.Dispose();
Wait(); Wait();
}
}
private void Wait()
{
System.Threading.Thread.Sleep(10);
System.Threading.Thread.SpinWait(1);
}
I don't get, why "ReadDataFromRS232" is beeing repeated until the timeout stops this task.
Thank you for any help :)
EDIT: Added some missing code.
As Dennis said the problem seemed to come from the missing volatile. It works now even though I have no idea why it didn't before.
I am running three same processes by using Process.start and by passing different arguments.I need a logic in way like only after completion of these proccess i have to execute last two methods named fourthmethod();sendmail();.How to do this.The existing logic is throwing these two method all the time,but i need only after the completion of three proccess ie three methods firstmethod();, secondmethod();, thirdmethod();
This code shows triggering three different process
// three same test.exe process
for(int i=0;i<3;i++)
{
Process.Start("test.exe",i);
}
In test.exe main method
Main(strin[] args)
{
if(args[0]==0)
{
firstmethod();
}
if(args[0]==1)
{
secondmethod();
}
if(args[0]==2)
{
thirdmethod();
}
fourthmethod();
sendmail();
}
using System;
using System.Diagnostics;
class Program
{
static int count = 0;
static object obj = new object();
static void Main(string[] args)
{
Process[] Processes = new Process[3];
for (int i = 0; i < 3; i++)
{
Processes[i] = Process.Start("notepad.exe");
Processes[i].EnableRaisingEvents = true;
Processes[i].Exited += Program_Exited;
}
Console.ReadLine();
}
private static void Program_Exited(object sender, System.EventArgs e)
{
lock (obj)
{
count++;
}
if (count == 3)
Console.WriteLine("Finised");
}
}
One Way to do it :)
Updated Code :
// three same test.exe process
for(int i=0;i<4;i++) // the two method should execute only after 3 processes
{
Process.Start("test.exe",i);
}
Updated code Test.exe
Main(strin[] args)
{
if(args[0]==0)
{
firstmethod();
}
if(args[0]==1)
{
secondmethod();
}
if(args[0]==2)
{
thirdmethod();
}
if(args[0]==3) // i shall increment to 3 only if the first three processes are ran
{
fourthmethod();
sendmail();
}
}
In a simple form app I'm running a constant thread when the app starts. Upon its first iteration everything goes smoothly and the thread method "Thread_ContinousChecker" works as intended. After it's run once and the the lockChecker.returnBlock() == true hits then it does not run again. Ie, does not attempt again. I have a hunch that it is something to do with the await lockChecker.checkTime() line but don't understand why, if it works once why would it stop?
Note : It only stops working if the first if statement in the Thread_ContinousChecker method hits, ie if lockChecker.returnBlock() method is true. If it's false, it continues on.
Here is my program class
static class Program
{
//Instantiate the lockform
static LockForm lockForm;
public static bool checkLockForm()
{
Form checker = Application.OpenForms["LockForm"];
return (checker == null);
}
public static void toggleLockForm(bool theBool)
{
//If theBool (our condition) is true start the form
if (theBool == true)
{
//Checks if form already eixsts
if (checkLockForm() == true)
{
//Starts the form
Application.Run(lockForm = new LockForm());
}
}
//Now if theBool is false - we want to close down any instances of the form that we may have started
if (theBool == false)
{
//This is saying if an instance of a LockForm exists
if (checkLockForm() == false)
{
//Rest of app does not close but that lockform is disabled.
//lockForm.Close();
Application.Restart();
}
}
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
MyController cont = new MyController();
//Start new thread for our lock checking
Thread thread = new Thread(new ThreadStart(cont.Thread_ContinuousChecker));
thread.IsBackground = true;
thread.Name = "Data Polling Thread";
thread.Start();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new TrayApp());
}
public class MyController
{
public Boolean checkForm()
{
if (Process.GetProcessesByName("ControlApp.exe").Length > 0)
{
// Is running
return true;
}
if (Process.GetProcessesByName("ControlApp.exe").Length == 0)
{
// Is not running - so start it
return false;
}
return false;
}
public async void Thread_ContinuousChecker()
{
while (true)
{
if (checkForm() == false)
{
LockLogic lockChecker = new LockLogic();
await lockChecker.checkTime();
if (lockChecker.returnBlock() == true)
{
Program.toggleLockForm(true);
}
if (lockChecker.returnBlock() == false)
{
Program.toggleLockForm(false);
}
}
Thread.Sleep(10000);
}
}
}
Here is my LockLogic's .checkTime() method which I'm awaiting in the above Program class
public async Task checkTime()
{
// Read values back from Json file
var serializedList = await Task.Run(() => File.ReadAllText(_filePathTimes));
// getting a list of LockTime objects
var lockTimeList = await Task.Run(() => (List<LockTime>)JsonConvert.DeserializeObject(serializedList, typeof(List<LockTime>), new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error }));
//
if (lockTimeList == null)
{
return;
}
if(lockTimeList.Count == 0)
{
return;
}
_lockTimes = lockTimeList;
//Then I do a foreach loop to go through every value in the start list and add the same located value to my listOfTimes (the list of LockTime objects with start and end)
for (int x = 0; x < _lockTimes.Count; x++)
{
TimeSpan start = new TimeSpan(_lockTimes[x].Start.Hour, _lockTimes[x].Start.Minute, _lockTimes[x].Start.Second);
TimeSpan end = new TimeSpan(_lockTimes[x].End.Hour, _lockTimes[x].End.Minute, _lockTimes[x].End.Second);
TimeSpan now = new TimeSpan(DateTime.Now.TimeOfDay.Hours, DateTime.Now.TimeOfDay.Minutes, DateTime.Now.TimeOfDay.Seconds);
if ((now > start) && (now < end))
{
_block = true;
}
else
{
_block = false;
}
}
}
A massive thanks to anyone who can spot what's going wrong.
I have a hunch that the problem is your use of Application.Run(lockForm = new LockForm());. As per http://msdn.microsoft.com/en-us/library/ms157902(v=vs.110).aspx, "This method adds an event handler to the mainForm parameter for the Closed event. The event handler calls ExitThread to clean up the application."
So, it's doing what you told it - binding the lifetime of the application to the lifetime of the newly created LockForm.
Hope this helps.
I am implementing a preemptive, exclusive function in a multithreaded environment, where if a cancel request occurs even when the function is not running, when the function does run, it knows about this cancel request and does not run. I came across various different ways to do this in C# using ManualResetEvent and the like(something like the answer to this question Synchronizing a Timers.Timer elapsed method when stopping), however I was wondering if something as simple as what I am doing in the code below would suffice. Are there any inadvertent bugs that I am introducing here?
bool cancel = false;
bool running = false;
object Lock = new object();
void PremptiveExclusiveFunction() {
lock(Lock) {
if(running)
return;
running = true;
}
for(int i=0; i < numIter; i++) {
lock(Lock) {
if(cancel) {
cancel = false;
running = false;
return;
}
}
// iteration code
}
lock(Lock) {
running = false;
}
}
void Stop() {
lock(Lock) {
cancel = true;
}
}
As far as I know, this seems to handle my 3 requirements:
1. ability to preempt
2. exclusivity in time, where this only copy of this function can be running
3. a cancel request not being lost because Stop is called before PreemptiveExclusiveFunction
I'd be grateful if more experienced minds could point out if I am indeed missing something.
Entire function body can be locked to eliminate the running boolean:
object #lock = new object();
volatile bool cancel = false;
void Function () {
if (!Monitor.TryEnter(#lock))
return;
try {
for (var i = 0; i < 100; i++) {
if (cancel) {
cancel = false;
return;
}
// code
}
} finally {
Monitor.Exit(#lock);
}
}
void Stop () {
cancel = true;
}
+ Notice the volatile keyword:
http://msdn.microsoft.com/en-us/library/vstudio/x13ttww7(v=vs.100).aspx