Console application (C#) is stuck while interaction - c#

I’m writing console application which does some work by scheduler and write output to console. Everything is good but when I click on the console it stops working and waits for my right click. After that it continues working.
I thought that it simply doesn’t write text to console and does what it needs to do but no, it waits my interaction. I can rewrite this code to WinForms or WPF but I think it can be solved in another way. Here my code
static void Main(string[] args)
{
Console.WriteLine("Started...");
var timer = new System.Timers.Timer(1000);
timer.Elapsed += timer_Elapsed;
timer.Start();
Console.ReadLine();
}
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Console.WriteLine("Writing to file " + DateTime.Now.ToString());
System.IO.File.AppendAllLines(#"C:\Temp\log.txt",
new[] { DateTime.Now.ToString()});
}
After clicking on console it stops appending time to file log.txt.
Any ideas how to fix that? Thanks.

That’s standard console behavior, it waits your user input locking the execution thread.
To understand why it is look at Console.Write implementation. It simply writes to Console output (Console.Out property) which is by default synchronized TextWriter (source). So, the “magic” is here.
You can solve this by delegating console writing to dedicated thread. For instance in his way:
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
Task.Factory.StartNew(() =>
{
Console.WriteLine("Writing to file " + DateTime.Now.ToString());
});
System.IO.File.AppendAllLines(#"C:\Temp\log.txt",
new[] { DateTime.Now.ToString()});
}
So, your application will continue writing to file but will write text to console only when you do right click.
The problem of this implementation is that it can create a lot threads increasing ThreadPool.
Better implementation can be done for instance with some special TaskScheduler like with SequentialScheduler
static TaskFactory factory = new TaskFactory(new SequentialScheduler());
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
factory.StartNew(() =>
{
Console.WriteLine("Writing to file " + DateTime.Now.ToString());
});
System.IO.File.AppendAllLines(#"C:\Temp\log.txt",
new[] { DateTime.Now.ToString()});
}
It won’t increase ThreadPool. Another implementation also can be used but the main idea is – delegating console write to another thread which may be blocked by user, the working thread will be unblocked and continue working.

Advice on implementation
If you want to avoid putting a lot of work on the thread-pool for the simple purpose of writing some stuff to console, then queues are your friend. This also ensures the correct order of the messages, and gives you some additional control (like disposing of unimportant entries).
Create a console logger thread which reads off of a concurrent queue where you enqueue entries to write to the console. Do take note that if the console is blocked indefinitely, then the queue will eventually grow until you run out of memory -- that is if you do in fact enqueue millions of entries in that time.
Example:
static ConcurrentQueue<string> consoleQueue = new ConcurrentQueue<string>();
static ManualResetEventSlim itemEnqueuedEvent = new ManualResetEventSlim();
static void WriteToConsoleLoop(object state)
{
var token = (CancellationToken)state;
while (!token.IsCancellationRequested)
{
string entry;
while (consoleQueue.TryDequeue(out entry))
{
Console.WriteLine(entry);
}
try
{
itemEnqueuedEvent.Wait(token);
itemEnqueuedEvent.Reset();
}
catch (OperationCanceledException)
{
break;
}
}
}
static void WriteToConsole(string entry)
{
consoleQueue.Enqueue(entry);
itemEnqueuedEvent.Set();
}
static void Main(string[] args)
{
var cts = new CancellationTokenSource();
// Background or foreground, depends on how vital it is
// to print everything in the queue before shutting down.
var thread = new Thread(WriteToConsoleLoop) { IsBackground = true };
thread.Start(cts.Token);
WriteToConsole("Started...");
// Do your stuff...
cts.Cancel();
}

Related

Is Thread.Sleep the right thing to do in a .NET Core 2.0 console app?

Usually I avoid using Thread.Sleep except for testing or debugging code.
In the following example, I'm trying to run a console app which will run different classes that will trigger timer ticks at certain times. The idea is to add many more classes that run independent services.
At the moment I'm using, Thread.Sleep(10000); just to keep the console open to allow the code to run.
Surely the Thread.Sleep is blocking some resouces of the CPU?
Is there a better way? (This would be for both Windows and Linux)
while(true)
{
Thread.Sleep(10000);
}
Program:
class Program
{
private static CultureInfo culture = new CultureInfo("en-gb");
static void Main(string[] args)
{
LongRunningClass longRunningClass = new LongRunningClass();
while(true)
{
Thread.Sleep(10000);
}
}
}
Long Running Task:
public class LongRunningClass
{
private Timer timer;
private List<TimeSpan> ScheduleTimes = new List<TimeSpan>()
{
new TimeSpan(4,0,0),
new TimeSpan(6,0,0),
new TimeSpan(21,0,0),
new TimeSpan(23,0,0),
};
public LongRunningClass()
{
this.timer = new Timer(1000);
this.timer.Elapsed += new ElapsedEventHandler(OnTick);
this.timer.Start();
}
protected virtual void OnTick(object sender, ElapsedEventArgs e)
{
this.timer.Stop();
RunLongRunningTask();
double nextTickInterval = 0;
TimeSpan timeOfDayNow = DateTime.Now.TimeOfDay;
foreach (TimeSpan scheduleTime in ScheduleTimes)
{
if (scheduleTime > timeOfDayNow)
{
nextTickInterval = (scheduleTime - timeOfDayNow).TotalMilliseconds;
break;
}
}
// If tick interval not set yet then restart for next day
if (nextTickInterval <= 0)
{
TimeSpan scheduleTime = ScheduleTimes[0].Add(new TimeSpan(1, 0, 0, 0));
nextTickInterval = (scheduleTime - timeOfDayNow).TotalMilliseconds;
}
this.timer.Interval = nextTickInterval;
this.timer.Start();
}
private void RunLongRunningTask()
{
// Long Running Task
}
}
If it's about keeping the console open.
Did you try?
while(true)
{
Console.Read();
}
or just:
Console.Read();
so, it wouldn't close unless you press a key.
You can keep the console open indefinitely until the user cancels by using an AutoResetEvent:
class Program
{
private static AutoResetEvent autoResetEvent;
private static CultureInfo culture = new CultureInfo("en-gb");
static void Main(string[] args)
{
LongRunningClass longRunningClass = new LongRunningClass();
WaitForCancel();
}
/// <summary>
/// When cancel keys Ctrl+C or Ctrl+Break are used, set the event.
/// </summary>
private static void WaitForCancel()
{
autoResetEvent = new AutoResetEvent(false);
Console.WriteLine("Press CTRL + C or CTRL + Break to exit...");
Console.CancelKeyPress += (sender, e) =>
{
e.Cancel = true;
autoResetEvent.Set();
};
autoResetEvent.WaitOne();
}
}
Obviously, this method relies on you knowing when your threads have finished processing.
Surely the Thread.Sleep is blocking some resouces of the CPU?
Its not the CPU you have to worry about, its the memory. You can read the complicated version here, but the simple version is that each thread uses 1MB of memory for the stack. If you are writing an application which needs a lot of threads then you should consider writing async Methods and using Task.Delay. This allows the thread to do something else while the method is waiting, which can reduce the total number of threads needed to process the same workload.
In this case however there isn't much point - while C# 7.1 does support async Main, its just syntactic sugar and doesn't free the thread up to perform other work. In any case I wouldn't loose sleep over using Thread.Sleep in a simple console app like this, or alternatively using something like Console.ReadLine like Neos07 suggests.
Thread.Sleep does still work, but you can consider using Task.Delay as an alternative here, like
await Task.Delay(1000);

Canceling a Process started via System.Diagnostics.Process.Start()

I am writing an application where I have a Process running in a BackgroundWorker. I would like to support cancellation from the user interface, but I don't see an easy way to do this.
The Process is actually a fairly long running command line exe. The output is getting redirected asynchronously via the Progress.OutputDataReceived event and is being used to report progress to the GUI.
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
using (var process = new Process())
{
//...
process.Start()
//...
process.WaitForExit();
}
}
private void CancelWorker()
{
worker.CancelAsync();
// where to actually listen for the cancellation???
}
There doesn't appear to be a way to have the process "listen" for any input from the main thread aside from the StandardInput, but that won't work unless the app itself will response to a specific input to abort.
Is there a way to cancel a process based on a cancel request from the main thread?
For the purposes of my of the EXE running in the process, I can just call Process.Close() to exit without any side-effects, but the Process object is only known to the worker_DoWork() method, so I'll need to keep track of the Process instance for cancellation purposes... that's why I'm hoping there might be a better way.
(if it matters, I am targeting .NET 3.5 for compatibility issues.)
For cooperative cancellation, you need to listen to BackgroundWorker.CancellationPending
in BackgroundWorker.DoWork
event.
How to: Use a Background Worker
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
using (var process = new Process())
{
//...
process.Start()
//...
while(true)
{
if ((sender as BackgroundWorker).CancellationPending && !process.HasExited)
{
process.Kill();
break;
}
Thread.Sleep(100);
}
process.WaitForExit();
}
}
try this, this might be help you, in easy way
private System.Threading.TimerCallback worker;
private System.Threading.Timer workertimer ;
private void worker_DoWork()
{
//You codes
}
private void StartWorker()
{
worker = new System.Threading.TimerCallback(worker_DoWork);
workertimer = new System.Threading.Timer(worker, null, 1000, 1000);
}
private void CancelWorker()
{
worker.Dispose();
}

Using a semaphore instead of while loop. Is this good or bad?

I have a process that runs in it's own thread and can be started/stopped without blocking. This will eventually go into a Windows service, but I am setting this up in a console app for now until it is fully fleshed out.
After the call to Start(), I want the main program thread to block until Ctrl-C is pressed. I know that this will work:
public static void Main(string[] args)
{
bool keepGoing = true;
var service = new Service();
System.Console.TreatControlCAsInput = false;
System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
service.Stop();
keepGoing = false; // Break the while loop below
};
service.Start();
while( keepGoing )
{
Thread.Sleep(100); // 100 is arbitrary
}
}
However, I find the flag and arbitrary sleep value bothersome. I know that the CPU cost is practically 0 in the while loop, but I'd rather have a "hard" block that releases as soon as the Ctrl-C handler is done. I devised the below, using a semaphore to block until the anonymous Ctrl-C handler is done:
public static void Main(string[] args)
{
var service = new Service();
var s = new Semaphore(1, 1);
System.Console.TreatControlCAsInput = false;
System.Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
service.Stop();
s.Release(); // This will allow the program to conclude below
};
service.Start();
s.WaitOne(); // This will not block
s.WaitOne(); // This will block w/o CPU usage until the sempahore is released
}
Is this a bad design? Is it overkill? Is it dangerous?
EDIT:
I also hook up AppDomain.CurrentDomain.UnhandledException as follows:
AppDomain.CurrentDomain.UnhandledException += delegate {
service.Stop();
s.Release();
};
EDIT the 2nd:
I should note that it is crucial that the Stop() method get called on exit. #Adam Ralph has a perfectly good pattern for a hybrid console/service, but didn't have this information when answering the Q.
We have a similar requirement in a few of our apps. They are Windows services, but for debugging we often want to run them as console apps. Moreover, we usually code new apps as Windows services fairly early on but often don't want to have to actually run them as a service until later, once we've proved the concept, etc.
This is the pattern we use:-
using (var service = new Service())
{
if (Environment.UserInterActive)
{
service.Start();
Thread.Sleep(Timeout.Infinite);
}
else
{
ServiceBase.Run(service);
}
}
Telling the thread to sleep infinitely might seem inefficient, but this is only for debugging scenarios and the redundant thread costs no CPU time, just some memory (about 1MB), which is mostly composed of the stack space allocated to the thread. The process can still be exited with Ctrl+C or by closing the command window.
-- EDIT --
If you find that service.Dispose() is not being called when Ctrl+C is pressed (i.e. a rude abort happens) and the call to Dispose() is crucial, then I guess you could explicitly do this like so:-
using (var service = new Service())
{
if (Environment.UserInterActive)
{
Console.CancelKeyPress += (sender, e) => service.Dispose();
service.Start();
Thread.Sleep(Timeout.Infinite);
}
else
{
ServiceBase.Run(service);
}
}
Note that Stop() should be encapsulated in Dispose().

WPF/C# Cancelling BackgroundWorker call outside DoWork

I have a BackgroundWorker DoWork function as follows
private void WorkerGetFeedData(object sender, DoWorkEventArgs args)
{
_feed.FetchUserData(_userNameCollection);
}
The FetchUserData is a function in another class(whose object is _feed) in another project in the same solution. The data fetch process takes considerable time and I'd like for the user to be able to cancel the process if necessary. How do I convey a cancel operation from the user to a function call elsewhere and just stop it?
You can use BackgroundWorker.CancelAsync method. Here's more info with example: MSDN
To be more exact to your problem, pass the worker to FetchUserData. It is the sender parameter. Then in the FetchUserData function you can check if the flag BackgroundWorker.CancellationPending is set and finish your method.
void FetchUserData(IEnumerable<Users> userNameCollection, BackgroundWorker worker)
{
// ...
if(worker.CancellationPending)
{
// Finish method..
}
}
And the WorkerGetFeedData method:
private void WorkerGetFeedData(object sender, DoWorkEventArgs args)
{
var worker = sender as BackgroundWorker;
if(worker != null)
_feed.FetchUserData(_userNameCollection, worker);
}
Send a message (event) to the worker thread that changes a boolean, indicating that the worker thread should end/cancel itself.
Edit: I was a bit quick reading your question, missing the important part. While trying to make up I found this interesting article which might help:
http://ondotnet.com/pub/a/dotnet/2003/02/18/threadabort.html
It does work when simulating a long running process with Thread.Sleep(), being at work I dont have time right now to write code to test it on a proper application/long running task.
class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(new ThreadStart(Foo));
thread.Start();
Console.ReadKey();
thread.Abort(); // cause ThreadAbortException to be thrown
Console.ReadKey();
}
static void Foo()
{
try
{
while( true )
{
Console.WriteLine("Long running process...");
Thread.Sleep(100000);
}
}
catch( ThreadAbortException ex )
{
Console.WriteLine(ex.Message);
}
finally
{
Console.WriteLine("Thread Closing ...");
}
}
}
The problem with this approach is - it uses Thread.Abort() - which interrupts the thread no matter what it is doing. This can lead to left open handles, memory leaks, etc. So while it may help it would most likely be very unwise to use.
Ian Griffiths supposes that another way to (force) cancel a thread would be to run it in its own, seperate process: http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation which you can kill whenever without affecting your process's internal state.

Making a console application behave like a Windows application

I have a console application, and I want it to wait till some event is raised. But it executes the code and exits:
static void Main(string[] args)
{
var someObjectInstance = new SomeObject();
someObjectInstance.SomeEvent += SomeEventHandler;
}
static void SomeEventHandler()
{
//Some logic
}
I want to make my application behave like a Windows application where
Application.Run(new Form1());
is called and the message loop is run.
But I don't need neither a message loop nor any form. So it looks like overhead. Is there a more light-weight way to achieve my goal?
First off, unless SomeObject is going to raise the event on a separate thread, this won't work without some form of processing in SomeObject. If it's designed that way, however, this is fairly straightforward.
A very efficient way of handling this is to just wait on a WaitHandle:
private static ManualResetEvent waitHandle = new ManualResetEvent(false);
static void Main(string[] args)
{
var someObjectInstance = new SomeObject();
someObjectInstance.SomeEvent += SomeEventHandler;
waitHandle.WaitOne(); // Will block until event occurs
}
static void SomeEventHandler()
{
//some logic
waitHandle.Set(); // Will allow Main() to continue, exiting the program
}
Add
Console.ReadLine(); after you attach your eventhandler.
For example..
class Program
{
static void Main(string[] args)
{
System.IO.FileSystemWatcher watcher = new System.IO.FileSystemWatcher(#"c:\", "*.txt");
watcher.Created += new System.IO.FileSystemEventHandler(watcher_Created);
watcher.EnableRaisingEvents = true;
Console.ReadLine();
}
static void watcher_Created(object sender, System.IO.FileSystemEventArgs e)
{
Console.WriteLine(string.Format("{0} was created at {1:hh:mm:ss}", e.FullPath, DateTime.Now));
}
}
EDIT: Sadly, I was incorrect and this won't work, because Application is not defined for a console application (Thank you, Reed Copsey).
This should do the trick, although depending on the sleeptime you choose you could end up hogging the CPU. I feel like there must be a safer way to do this?
while (true)
{
Application.DoEvents();
Thread.Sleep(this.SleepTime);
}

Categories

Resources