Restarting a method - c#

I am making a C# aplication. I have got one main process for verifying data from a database. A timer checks every 100 ticks if I have user input. After I get user input my main process continues (it waits for userinput at the start). After verifying and doing multiple things the method is done. The thing is, I would like it to go to the beginning again waiting for the next bit of input.
I was thinking of calling the method again at every possible end of the process. I have a feeling that this will create a resource heavy program though (not the worst thing, but better no bad habits than a few right?).
Example:
bool cont = false;
public void process()
{
while (cont == false) {;}
//Various sorting criteria that all end up with cont = false; process(), the userinput has been processed.
}
timer1 tick event
{
if (userinput)
cont = true;
}

As you don't saw how you will get the user input, i don't implemented this one. But the main logic to your question is :
class MainClass
{
public static void Main()
{
MyRecursiveFunction();
AfterUserInput();
}
public static void MyRecursiveFunction()
{
if (userinput)
{ return; }
// Waits 100 ticks to check again
Thread.Sleep(new TimeSpan(100));
MyRecursiveFunction();
}
public static void AfterUserInput()
{
// All that you need to do after the user input
}
}

Related

Best solution for stopping a piece of code to be called multiple times?

I have a method which is been called every 1 hour. But sometimes the method operations are not been completed fully within one hour and the method is again been called which causes confusion. So I have to find out if the previous method is been completed. Which is the best solution for this problem?
// will be called for every one hour where the value will be repeated
// At sometimes it is possible for the same value to be called continually
for the next hour and at that time problem occurs
Void Method(int value)
{
If(value =0)
// Do some operations which may exceed one hour
Else If(value =1)
// Do some operation’s which may exceed one hour
.
.
.
}
Thanks,
One question would be what do you want to happen if the method is called while it is still running?
This code will just drop the 2nd call
private bool _running = false;
private readonly object _lock = new object();
void Method(int value)
{
lock (_lock)
{
if (_running)
{
return;
}
else
{
_running = true;
}
}
if (value == 0)
{
// Do some operations which may exceed one hour
}
else if (value == 1)
{
// Do some operation’s which may exceed one hour
}
_running = false;
}
A simple idea is to save the state in a class field, so that the method checks to see if it's free to do some work or not. This will mean that if you call the method and it's busy, the work won't happen for your call:
private static bool methodIsBusy = false;
private static void WaitAndWriteMessage(TimeSpan waitTime, string message)
{
// If we're busy, return right away
if (methodIsBusy) return;
// Let future calls know we're busy
methodIsBusy = true;
Thread.Sleep(waitTime);
Console.Write($"Method ran at: {DateTime.Now.ToString("hh:mm:ss")}. ");
Console.WriteLine(message);
// Allow future calls to run now
methodIsBusy = false;
}
Our test method:
private static void Main()
{
for(int i = 0; i < 3; i++)
{
Task.Run(() => WaitAndWriteMessage(TimeSpan.FromSeconds(5),
$"Method called at {DateTime.Now.ToString("hh:mm:ss")}."));
Thread.Sleep(1000);
}
Console.ReadKey();
GetKeyFromUser("\nDone!\nPress any key to exit...");
}
Output
(Only the first of the three messages was printed)
Another idea is to use a lock, which means that calls to the method will pile up if the method is busy. All calls will eventually get completed, but if every call is longer than the iteration time in which the method is called, it will get further and further behind:
private static object methodLocker = new object();
private static void WaitAndWriteMessage(TimeSpan waitTime, string message)
{
// Lock on a common object, so this call will wait
// until there are no locks before it can continue
lock (methodLocker)
{
Thread.Sleep(waitTime);
Console.Write($"Method ran at: {DateTime.Now.ToString("hh:mm:ss")}. ");
Console.WriteLine(message);
}
}
Our test method again:
private static void Main()
{
for(int i = 0; i < 3; i++)
{
Task.Run(() => WaitAndWriteMessage(TimeSpan.FromSeconds(5),
$"Method called at {DateTime.Now.ToString("hh:mm:ss")}."));
Thread.Sleep(1000);
}
Console.ReadKey();
}
Output
(Notice the difference between when the message was called and when it executed gets longer each time)

How to stop function being called too often

There is a function which checks license with hardware key. But this function is getting called too often and takes time to execute. So to avoid too many call I want to check license after sometime.
bool CheckLicense()
{
if(license checked in last 10 secconds)
{
return last status;
}
else
{
hardware access for license check
return current status
}
}
Edit: Hardware key might be removed so checking once is not good practice. Also license check is to be called for enabling and disabling different button status.
In general, I think you would need something like this.
private DateTime lastCheckTime = DateTime.Now.AddDays(-1);
bool CheckLicense()
{
if (lastCheckTime.AddSeconds(10) < DateTime.Now)
return last_status;
lastCheckTime = DateTime.Now;
// hardware access for license check
return current_status
}
If you want to call it just once every 10 seconds you could use the following:
bool CheckLicense()
{
bool currentStatus = false;
//hardware access for license check
new Thread(() =>
{
Thread.Sleep(10000);
CheckLicense();
}).Start();
return currentStatus;
}
You call it once in your code and then every 10 seconds it will call itself.
Checking the licence every 10 seconds will definitely gonna add to many calls for the same function. You can do it once when the program starts as suggested in the comments whereas if it is really necessary for you to check the license or calling a function after every some time you can actually increase the timings so that you know you have checked the licence and calls will be reduced.
Like for example you checked the licence for the first time when the program starts than after that about 10 seconds and then increase the timing by 10*2 which would be 20 than next time increase it by 20*2 which becomes 40 and this will lessens the call as well as you will be checking it every few times.
bool CheckLicense()
{
timelimit = 300;
if(seconds > timetocheck)
{
return last status;
timetocheck *= 2;
if(timetocheck >= timelimit)
{
timetocheck = 10;
}
}
else
{
hardware access for license check
return current status
}
}
The program is just a prototype and doesnt mean to run directly it also does not talk about the datatypes and syntax. This is just for the understand-ability.
If You are doing this checks in sync. code, You might want to run new thread instead. And if there is problem with license, the separate thread will inform Your main thread through events:
class LicenseChecker
{
private Timer mTimer;
public delegate void LicenseNotValidDelegate();
public event LicenseNotValidDelegate LicenseNotValid;
public LicenseChecker()
{
mTimer = new Timer();
mTimer.Ticket += mTimer_Tick;
mTimer.Interval = TimeSpan.FromSeconds(10);
}
public void Start()
{
mTimer.Start();
}
void mTimer_Tick(object sender, EventArgs e)
{
if(!CheckLicense())
LicenseNotValid?.Invoke();
}
private bool CheckLicense()
{ ... }
}
...
public void Main()
{
var lLC = new LicenseChecker();
lLC.LicenseNotValid += lLC_LicenseNotValid;
lLC.Start();
}
void lLC_LicenseNotValid()
{
//code when license is not valid
}

ontextchanged async sql stored proc call

I have a winform application and on the main form I placed a textbox.
What I want is that on the OnTextChanged event I need to query sql (stored proc) table in order to bring a list of matches with the character typed. For example if I type letter A then automaticly I should go and search in the database for names starting with letter "A", if I then type letter "L" then I should go and search for names starting with "AL" and so on.
The thing is that If I the user type fast then It should cancel any async process that is in progress and keep only the task for the last letter typed.
Any clue on how to achieve these?
The thing is that If I the user type fast then It should cancel any async process
It shouldn't need to cancel anything - the trick is not to start anything until you think the user has stopped typing.
I wrote something a bit similar, whereby when the user typed I had a thread start a new method, the method waited for a (configurable) time before executing. Another keystroke would call the method again and reset the wait period - effectively if someone continued to type the task wouldn't execute; as soon as they stopped it would (after a 200 ms pause for example).
I would implement something similar if I were you, as it avoids going to SQL when you don't have to
updated - by way of a simple example, a new project with a new form and default text box should allow the following code to function for your needs (as a very simple starting point)
public partial class Form1 : Form
{
private bool _waiting;
private bool _keyPressed;
private const int TypingDelay = 220; // ms used for delay between keystrokes to initiate search
public Form1()
{
InitializeComponent();
}
private void WaitWhileUserTyping()
{
var keepWaiting = true;
while (keepWaiting)
{
_keyPressed = false;
Thread.Sleep(TypingDelay);
keepWaiting = _keyPressed;
}
Invoke((MethodInvoker)(ExecuteSearch));
_waiting = false;
}
private void ExecuteSearch()
{
Thread.Sleep(200); // do lookup
// show search results...
MessageBox.Show("Search complete");
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (_waiting)
{
_keyPressed = true;
return;
}
_waiting = true;
// kick off a thread to do the search if nothing happens after x ms
ThreadPool.QueueUserWorkItem(_ => WaitWhileUserTyping());
}
}

How to stop a running method with keyboard input in a Console Application on C#?

In short, I'm utilizing C# to scientific computation and I've written a method that has a while loop that may run to a user-specified quantity of steps... Actually, this method may take too long to execute (like more than 5 hours). When it takes this long, I may want to stop the method pressing Esc key, for example.
As I read something about breaking while, it is as simple as a Boolean flag or something like this. So I thought in something like this:
public Double? Run(int n)
{
int i = 0;
while ((i < n) && (/* inputkey != ConsoleKey.Escape */))
{
// here goes the heavy computation thing
// and I need to read some "inputkey" as well to break this loop
i++;
}
// I'm not worried about the return statement, as it is easy to do...
// returns null if the user skipped the method by pressing Escape
// returns null if the method didn't converged
// returns the double value that the method calculated otherwise
}
Well, this is what I wondered until now... So please, could you give useful ideas to this extent? How can I wait for a user input (I thought about Events, but I'm not sure how to implement it here and I think that it will make the code even slower, if I have to listen to a key at every while step the code goes into...
Well, any ideas or comments?
Update: I think I should have had described better the problem. All the solutions you gave me may solve this problem I proposed, but I think I was not completely reliable to my real problem. I don't know if I should ask another question or keep with this one...
You could run this method from a separate thread and set a stop variable when a key is pressed:
object myLock = new object();
bool stopProcessing = false;
public Double? Run(int n)
{
int i = 0;
while (i < n)
{
lock(myLock)
{
if(stopProcessing)
break;
}
// here goes the heavy computation thing
// and I need to read some "inputkey" as well to break this loop
i++;
}
}
and when a key is pressed, update stopProcessing accordingly:
Console.ReadKey();
lock(myLock)
{
stopProcessing = true;
}
If you're just wanting to stop the application, Ctrl-C from the command line will do it. If you really need to intercept input during a long running process, you might want to spawn a worker thread to do the long running process and then just use the main thread to interact with the console (i.e. Console.ReadLine()).
You will need to do this using threading. When you start the task, spawn a new thread and execute the task on that thread. Then in your Program.cs, wait for user input. If the user enters something meaningful - in your case, the Esc key - alert the background thread of the action. The simplest way to do this is by setting a static variable. The background thread will be checking this static variable and when it has been changed, the background thread will clean itself up and abort.
See the MSDN article on Threading.
A code sample will be a little more in depth, but it would look something like this:
public class Program.cs
{
public static myFlag = false;
public void Main()
{
thread = new Thread(new ThreadStart(DoWork));
thread.Start();
Console.ReadLine();
myFlag = true;
}
public static DoWork()
{
while(myFlag == false)
{
DoMoreWork();
}
CleanUp()
}
public static DoMoreWork() { }
public static CleanUp() { }
}
pool on Console.KeyAvailable in timely manner and take the action accordingly.
using System;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Program
{
static bool _cancelled = false;
static void Main( string[] args )
{
var computationTask = Task.Factory.StartNew(PerformIncredibleComputation);
var acceptCancelKey = Task.Factory.StartNew(AcceptCancel);
while (!acceptCancelKey.IsCompleted && ! computationTask.IsCompleted)
{
computationTask.Wait (100);
}
if( acceptCancelKey.IsCompleted && !computationTask.IsCompleted )
{
computationTask.Wait (new System.Threading.CancellationToken ());
}
else if(!acceptCancelKey.IsCompleted)
{
acceptCancelKey.Wait(new System.Threading.CancellationToken());
}
}
private static void PerformIncredibleComputation()
{
Console.WriteLine("Performing computation.");
int ticks = Environment.TickCount;
int diff = Environment.TickCount - ticks;
while (!_cancelled && diff < 10000)
{
//computing
}
Console.WriteLine("Computation finished");
}
private static void AcceptCancel()
{
var key = Console.ReadKey(true);
Console.WriteLine("Press Esc to cancel");
while(key.Key != ConsoleKey.Escape)
{
key = Console.ReadKey(true);
}
_cancelled = true;
Console.Write("Computation was cancelled");
}
}
}

breaking out of my infinite loop

I have two buttons one for start and one for stop in my UI form,and i have one infinite loop that executes some function in my class name programs in a method.The start button is clicked by the user it invokes this method to execute the infinite loop and i need to break this infinite loop when the user clicks the stop button,after that my compiler will break out of this infinite loop and enters to the code inside the button stop click.
I am trying to use the Application.DoEvents() method,this is working well if my infinite loop code is inside of the start button click,but if my infinite loop code is in the new class which is created by me i.e programs,how can use the Application.DoEvents() method to break out of this infinite loop.
Example:
namespace inFiniteLoopTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
bool stopBtnClk = false;
bool startBtnClk = false;
private void StartBtn_Click(object sender, EventArgs e)
{
stopBtnClk=false;
startBtnClk = true;
while(true)
{
//some code to be executed
Application.DoEvents();
if (stopBtnClk == true)
{
break;
}
}
}
private void StopBtn_Click(object sender, EventArgs e)
{
stopBtnClk = true;
if (startBtnClk == true)
{
//Application.Exit();
MessageBox.Show("success");
}
}
this is working well.
But
public class programs
{
public static void infiniteLoop(bool stopBtnClick)
{
while(true)
{
//some code to be executed
Application.DoEvents();
if (stopBtnClk == true)
{
break;
}
}
}
}
//and my UI code to call this class is
namespace inFiniteLoopTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
bool stopBtnClk = false;
bool startBtnClk = false;
private void StartBtn_Click(object sender, EventArgs e)
{
stopBtnClk=false;
startBtnClk = true;
programs.infiniteLoop(stopBtnClk);
}
private void StopBtn_Click(object sender, EventArgs e)
{
stopBtnClk = true;
if (startBtnClk == true)
{
//Application.Exit();
MessageBox.Show("success");
}
}
}
but this is not working .
Even if the compiler displays the message "success" when the stop button is clicked, but the debugger still said running in my form.
I hope my question is clear.
And i am kindly requesting you to answer my question as soon as possible and get rid of this problem!
I openly accept your answer if you come especially with a thread.
sorry i am a beginner for C#, but i need to continue on that.
Thank you!!
Don't block the GUI thread. The fact that you have to use Application.DoEvents() to update the GUI is an indicator for bad design. Do the work in a separate worker thread.
BackgroundWorker is predestinated for such a task.
Change signature of your infiniteLoop method like this:
public static void infiniteLoop(ref bool stopBtnClick)
...
The code you have provided is really difficult to read but as far as I can see when you create your infinite loop do:while(looping) // do stuff
Then when you press the Stop button set the bool variable looping to false and it will break out of the loop and show the message.
In the second code snippet, the infinite loop is started in a subroutine that accepts a boolean value as a parameter. How does that subroutine ever get a second chance to take a look at that boolean? It only "sees" the value once, and it's false at that time. It's a scoping question.
Why instead of an infinite loop you use a start stop condition determined by the buttons?
I thinking you can have a variable, just call it
bool stop_loop = false
and your loop
while(!stop_loop){ //CODE HERE }
Now when you click the first button (Start) you call the method (wherever it is) to start the loop. The loop is going to seem endless until you click the button stop and the value of stop_loop become in True.
HTH

Categories