I've code which starts depending whether the underlying application runs in console services instead of threads for the tasks. Here is a small cut of the main method:
//ANSAR BANK THREAD
Thread AnsarBankThread = new Thread(Ansar);
Console.WriteLine("Start The AnsarBankThread");
AnsarBankThread.Start();
//MELLAT BANK THREAD
Thread MellatBankThread = new Thread(Mellat);
Console.WriteLine("Start The MellatBankThread");
MellatBankThread.Start();
This is the code which will be executed:
static void Ansar()
{
var AnsarBank1 = new AnsarBank();
if (Environment.UserInteractive)
{
AnsarBank1.Start();
}
else
{
var servicesToRun = new ServiceBase[]{ AnsarBank1 };
ServiceBase.Run(servicesToRun);
}
}
static void Mellat()
{
var MellatBank1 = new MellatBank();
if (Environment.UserInteractive)
{
MellatBank1.Start();
}
else
{
var servicesToRun = new ServiceBase[]{ MellatBank1 };
ServiceBase.Run(servicesToRun);
}
}
and this is my AnsarBank service code:
protected override void OnStart(string[] args)
{
var timer = new System.Timers.Timer(5000); // fire every 30 second
timer.Elapsed += OnElapsedTime;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
File.WriteAllText(#"d:\Temp\Ansar.txt", "Ansar Bank Writer\n");
}
public void Start()
{
OnStart(new string[0]);
}
And this is my MellatBank Service:
protected override void OnStart(string[] args)
{
var timer = new System.Timers.Timer(5000); // fire every 30 second
timer.Elapsed += OnElapsedTime;
timer.Enabled = true;
}
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
File.WriteAllText(#"d:\Temp\MellatBank.txt", "Mellat Bank writer\n");
}
public void Start()
{
OnStart(new string[0]);
}
However, if I run the code there will be only the file Ansar.txt created and the file MellatBank.txt is missing!
Can someone encounter the problem in my code please? I would appreciate any help!
Chnage code to this:
System.Timers.Timer personalTimer = null;
public AnsarBank()
{
personalTimer = new System.Timers.Timer(5000);
InitializeComponent();
}
protected override void OnStart(string[] args)
{
//var timer = new System.Timers.Timer(5000); // fire every 30 second
personalTimer.Elapsed += OnElapsedTimeAnsar;
personalTimer.Enabled = true;
}
but so not work.
What's the problem?
1. Variable goes out of scope:
Thanks to #MatthewWatson: I also suggest moving the timer variable outside of the method right into the class. The timer object can be garbage collected directly because the garbage collector doesn't see that it's used any further.
Why thinks the gc that the variable isn't used anymore?
Simply because you created it in the method. It's local and because the class itself hasn't any reference to it there isn't any hint for the gc that it's needed further!
This should be true after I looked to this question.
Solution to this in sample code:
class SomeClass {
System.Timers.Timer personalTimer = null; //Timer is now garbage collected after the object of SomeClass goes out of scope!
SomeClass() {
personalTimer = new Syste.Timers.Timer(30000) // Now every 30 seconds!
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTime;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
}
....
}
2.File access problems
After I tried your code I encountered exceptions because the path may not exist. So I changed the code to create a path before the creation of a file. Also I added checks whether file exists and if so that text will be applied to the file. The old solution replaced the file everytime. This works for me fine. I don't know what you've done with InitializeComponents(...) this seems to be gui stuff, so I don't know.
Change your code in the service classes to following please:
namespace WebService
{
partial class MellatBank : ServiceBase
{
System.Timers.Timer personalTimer = null;
public MellatBank()
{
personalTimer = new System.Timers.Timer(1000);
this.ServiceName = "MellatBankService";
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTimeMellat;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
//var timer = new System.Timers.Timer(5000); // fire every 30 second
//personalTimer.Elapsed += OnElapsedTimeMellat;
//personalTimer.Enabled = true;
}
private void OnElapsedTimeMellat(object source, ElapsedEventArgs e)
{
try
{
if (!Directory.Exists(#"D:\Temp"))
Directory.CreateDirectory(#"D:\Temp\");
if (!File.Exists(#"D:\Temp\MellatBank.txt"))
{
var f = File.CreateText(#"D:\Temp\MellatBank.txt");
f.Write(#"D:\Temp\MellatBank.txt", "Mellat Bank writer\n");
f.Close();
}
else
{
var f = File.AppendText(#"D:\Temp\MellatBank.txt");
f.Write("Mellat Bank writer\n");
f.Close();
}
}
catch (System.Exception ex)
{
Console.Error.WriteLine("IO EXCEPTION: {0}", ex.ToString());
}
}
public void Start()
{
OnStart(new string[0]);
}
protected override void OnStop()
{
Console.Out.WriteLine("ended!");
// TODO: Add code here to perform any tear-down necessary to stop your service.
}
}
}
namespace WebService
{
partial class AnsarBank : ServiceBase
{
System.Timers.Timer personalTimer = null;
public AnsarBank()
{
personalTimer = new System.Timers.Timer(1000);
this.ServiceName = "AnsarBankService";
}
protected override void OnStart(string[] args)
{
personalTimer.Elapsed += OnElapsedTimeAnsar;
personalTimer.AutoReset = true; //Add this line to keep continuos activation
personalTimer.Enabled = true;
//var timer = new System.Timers.Timer(5000); // fire every 30 second
//personalTimer.Elapsed += OnElapsedTimeAnsar;
//personalTimer.Enabled = true;
}
private void OnElapsedTimeAnsar(object source, ElapsedEventArgs e)
{
try
{
if (!Directory.Exists(#"D:\Temp"))
Directory.CreateDirectory(#"D:\Temp\");
if (!File.Exists(#"D:\Temp\Ansar.txt"))
{
var f = File.CreateText(#"D:\Temp\Ansar.txt");
f.Write(#"D:\Temp\Ansar.txt", "Ansar Bank writer\n");
f.Close();
}
else
{
var f = File.AppendText(#"D:\Temp\Ansar.txt");
f.Write("Ansar Bank Writer\n");
f.Close();
}
}
catch (System.Exception ex)
{
Console.Error.WriteLine("IO EXCEPTION: {0}", ex.ToString());
}
}
public void Start()
{
OnStart(new string[0]);
}
protected override void OnStop()
{
Console.Out.WriteLine("ended!");
}
}
}
Edit:
After viewing your code I saw that your services only run as long as your application runs. So your services may have been stopped before they could write anything which would explain your problem too.
PS:
Asker please practice the basics of Object Oriented Programming (OOP) again if you don't know what class fields are.
Related
Is it possible to optimise my console application? It uses up to 60% of CPU because of while(true) loop.
The idea is to kill Microsoft managment console (services) process every time it starts up. And to start/stop services - use pswrd and console.
public static void Main(string[] args)
{
Thread consoleInput = new Thread(_consoleInput);
consoleInput.Start();
killProcess();
}
static void _consoleInput(){
getPassword();
sendServiceCommands();
}
static void killProcess(){
while(true){
try{
System.Diagnostics.Process[] myProcs = System.Diagnostics.Process.GetProcessesByName("mmc");
myProcs[0].Kill();
}
catch(Exception e){}
}
}
You need System.Threading.Timer. Something like this:
public class Killer
{
protected const int timerInterval = 1000; // define here interval between ticks
protected Timer timer = new Timer(timerInterval); // creating timer
public Killer()
{
timer.Elapsed += Timer_Elapsed;
}
public void Start()
{
timer.Start();
}
public void Stop()
{
timer.Stop();
}
public void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
System.Diagnostics.Process[] myProcs = System.Diagnostics.Process.GetProcessesByName("mmc");
myProcs[0].Kill();
}
catch {}
}
}
...
public static void Main(string[] args)
{
Killer killer = new Killer();
Thread consoleInput = new Thread(_consoleInput);
_consoleInput.Start();
killer.Start();
...
// whenever you want you may stop your killer
killer.Stop();
}
I'm trying to get weather information using ForecastIOPortable library.
I have a method that works without problems in Console application, same in WPF application.
ForecastApi api = new ForecastApi("XXXX");
var forecast = api.GetWeatherDataAsync(XXXX, XXXX);
var results = forecast.Result;
int tempC = (int)(5.0 / 9.0 * (results.Currently.Temperature - 32));
Problem shows when I try to call that method with tick of timer, program freezes and VS doesn't show information about exception.
When I checked breakpoints, I get information that results doesn't change and all time has value=null.
What is the reason of problem and how to deal with it?
You are using an async process so you will you will be getting the a Task rather than the result.
In a console app you generally have to .Wait() for the task to resolve before the result will be populated. You would be better to test using a WPF application where you can await the GetWeatherDataAsync method.
Probably the best way to handle it is to wrap the timer in a class and pass in the various bits.
You can try this
public class ForecastApiAsyncTimer : IDisposable
{
private ForecastApi _api;
private Timer _timer;
public ForecastApiAsyncTimer(Timer timer, ForecastApi forecastApi)
{
if (timer == null)
throw new ArgumentNullException("timer");
if (forecastApi == null)
throw new ArgumentNullException("forecastApi");
_api = forecastApi;
_timer = timer;
_timer.Elapsed += _timer_Elapsed;
}
public ForecastApiAsyncTimer(double interval, ForecastApi forecastApi)
{
if (forecastApi == null)
throw new ArgumentNullException("forecastApi");
_api = forecastApi;
_timer = new Timer(interval);
_timer.Elapsed += _timer_Elapsed;
}
public void Start()
{
_timer.Start();
}
public void Stop()
{
_timer.Stop();
}
protected async virtual Task<int> TimerElapsedTask()
{
var forecast = await _api.GetWeatherDataAsync(40.7505045d, -73.9934387d);
int tempC = (int)(5.0 / 9.0 * (forecast.Currently.Temperature - 32));
return tempC;
}
async void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
int result = await TimerElapsedTask();
// do something with result.
}
~ForecastApiAsyncTimer()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposing || _timer == null)
return;
_timer.Dispose();
_timer = null;
}
}
Example usage 1.
static void Main(string[] args)
{
string apiKey = "yourApiKey";
ForecastApi api = new ForecastApi(apiKey);
using (var forecastTimer = new ForecastApiAsyncTimer(5000, api))
{
forecastTimer.Start();
while (!Console.KeyAvailable)
{
}
}
}
Example usage 2:
static void Main(string[] args)
{
string apiKey = "yourApiKey";
ForecastApi api = new ForecastApi(apiKey);
Timer timer = new Timer(5000);
var forecastTimer = new ForecastApiAsyncTimer(timer, api);
forecastTimer.Start();
while (!Console.KeyAvailable)
{
}
}
I have a C# library, inside which there is a timer that keeps checking a boolean variable ProcessFinished. ProcessFinished is initialized as false.
What I want is that the main application needs to watch the variable Status from the library, and a message box should display once this ProcessFinished becomes true.
The problem I had is the message box never display if I simple execute the main application, but it displays if I step in the main application.
Here is the timer_tick code in main application:
public Window1()
{
_fl = new FijiLauncherControl();
this._statusTimer = new System.Windows.Forms.Timer(); // read log 4 times per sec
this._statusTimer.Interval = 125;
this._statusTimer.Tick += new EventHandler(_statusTimer_Tick);
InitializeComponent();
}
void _statusTimer_Tick(object sender, EventArgs e)
{
try
{
if (_fl.ProcessFinished)
{
System.Windows.MessageBox.Show("Process is finished");
_statusTimer.Stop();
}
}
catch (Exception ex)
{
}
}
private void FijiLaucherButton_Click(object sender, RoutedEventArgs e)
{
_statusTimer.Start();
_fl.LaunchFiji();
}
where the _fl is the object of the class from the other library.
Inside the library, the timer code is like this:
public FijiLauncherControl()
{
_ijmFile = "";
_fijiExeFile = "";
_logFile = "";
_outputDir = "";
_isLogOn = false;
_processOn = false;
_processFinished = false;
_headless = true;
_doneStr = "Procedure is finished.";
_logFileCheckTimer = new System.Timers.Timer(500); // read log 4 times per sec
_logFileCheckTimer.Enabled = true;
_logFileCheckTimer.Elapsed += new System.Timers.ElapsedEventHandler(_logFileCheckTimer_Elapsed);
}
void _logFileCheckTimer_Elapsed(object sender, EventArgs e)
{
if (_processOn && IsLogOn)
{
try
{
_processFinished = CheckStatuts();
}
catch (Exception ex)
{
}
}
}
I am wondering what is going on here? Is there anyway I can see the message box shows up without stepping in? What is the right way to watch ProcessFinished from the main application?
Would it not be better to fire an event from the thread and catch it. Then show the message box?
Like this maybe?
using System;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click( object sender, EventArgs e )
{
var logChecker = new LogChecker();
logChecker.FinishedExvent += () => MessageBox.Show( "Finished" );
logChecker.Start();
}
}
internal class LogChecker
{
public void Start()
{
var thread = new Thread( CheckLog );
thread.Start();
}
private void CheckLog()
{
var progress = 0;
while ( progress < 3000 )
{
Thread.Sleep( 250 );
progress += 250;
}
FinishedExvent();
}
public event TestEventHandler FinishedExvent;
}
internal delegate void TestEventHandler();
}
Try
volatile bool _processFinished;
I'm building a Windows Service using System.Timers.Timer. The tasks computed by the Timer's delegate can take from several seconds to several minutes. I would like to make sure that, when the service is stopped, all delegated threads currently running complete before being disposed.
Here is the code, however it does not do what I expect, as currently running threads never complete if the Windows Service is stopped while they are running.
public abstract class AgentServiceBase : ServiceBase
{
private System.ComponentModel.IContainer components = null;
private System.Timers.Timer _Timer;
private string _logPath;
private const int MAXNUMBEROFTHREADS = 10;
protected int interval = 25000;
protected int numberOfAllowedThreads = 2;
public AgentServiceBase()
{
this.InitializeComponent();
this._logPath = (Path.GetDirectoryName(Assembly.GetAssembly(this.GetType()).CodeBase)).Substring(6).Replace("/", #"\");
}
protected override void OnStart(string[] args)
{
if (args.Length > 0)
{
int.TryParse(args[0], out interval);
}
if (args.Length > 1)
{
int.TryParse(args[1], out numberOfAllowedThreads);
if (numberOfAllowedThreads > MAXNUMBEROFTHREADS)
{
numberOfAllowedThreads = MAXNUMBEROFTHREADS;
}
if (numberOfAllowedThreads == 1)
{
numberOfAllowedThreads = 2;
}
}
ThreadPool.SetMaxThreads(numberOfAllowedThreads, numberOfAllowedThreads);
this._Timer = new System.Timers.Timer();
this._Timer.Elapsed += new ElapsedEventHandler(PollWrapper);
this._Timer.Interval = this.interval;
this._Timer.Enabled = true;
}
protected override void OnStop()
{
this._Timer.Enabled = false;
Process currentProcess = Process.GetCurrentProcess();
foreach (Thread t in currentProcess.Threads)
{
t.Join();
}
}
/// <summary>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "Agent Service - Johnhenry";
}
private void PollWrapper(object sender, ElapsedEventArgs e)
{
try
{
this.Poll(sender, e);
}
catch (Exception exception)
{
string message = this.GetType().FullName + " - Windows Service Exception\n";
message += exception.GetNestedExceptionInSingleStringOutput();
FileHelper.Log(message, this._logPath, "exception", FileHelper.LogFileNameChangeFrequency.DAYLY);
}
}
protected abstract void Poll(object sender, ElapsedEventArgs e);
}
Many thanks,
Giuseppe
UPDATE:
After few different attempts with counting the current process's own threads I eventually settled with a simpler solution which is using a counter of the threads the timer had initiated and are still running. Based on that I call the Sleep on the main thread and issue a RequestAdditionalTime until all threads have ended.
Following the revised 2 methods:
protected override void OnStop()
{
this._Timer.Enabled = false;
while (numberOfRunningThreads > 0)
{
this.RequestAdditionalTime(1000);
Thread.Sleep(1000);
}
}
private void PollWrapper(object sender, ElapsedEventArgs e)
{
numberOfRunningThreads++;
try
{
this.Poll(sender, e);
}
catch (Exception exception)
{
string message = this.GetType().FullName + " - Windows Service Exception\n";
message += exception.GetNestedExceptionInSingleStringOutput();
FileHelper.Log(message, this._logPath, "exception", FileHelper.LogFileNameChangeFrequency.DAYLY);
}
finally
{
numberOfRunningThreads--;
}
}
You can achieve that by calling RequestAdditionalTime as long as your threads haven't finished the work yet in your implementation of OnStop inside the loop (before and/or after the call to Join()).
BUT BEWARE that Windows can get impatient and decide to kill your Windows Service - for example during shutdown...
For more information see the MSDN reference at http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.aspx
My question is that is this the best practice to do this. Couldn't find any good examples. I have following code in file created by VS2005:
public partial class ObjectFolder : ServiceBase
{
protected override void OnStart(string[] args)
{
ObjectFolderApp.Initialize();
ObjectFolderApp.StartMonitorAndWork();
}
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to stop yourservice.
}
}
then:
class ObjectFolderApp
{
public static bool Initialize()
{
//all init stuff
return true;
}
public static void StartMonitorAndWork()
{
Thread worker = new Thread(MonitorAndWork);
worker.Start();
}
private static void MonitorAndWork()
{
int loopTime = 60000;
if (int.TryParse(_cfgValues.GetConfigValue("OfWaitLoop"), out loopTime))
loopTime = 1000 * loopTime;
while (true)
{
/* create+open connection and fill DataSet */
DataSet ofDataSet = new DataSet("ObjectFolderSet");
using (_cnctn = _dbFactory.CreateConnection())
{
_cnctn.Open();
//do all kinds of database stuff
}
Thread.Sleep(loopTime);
}
}
}
Re-hashing my answer from this question, the recommended way is to use a timer and the following code:
public class MyService : ServiceBase
{
private Timer workTimer; // System.Threading.Timer
protected override void OnStart(string[] args)
{
workTimer = new Timer(new TimerCallback(DoWork), null, 5000, 5000);
base.OnStart(args);
}
protected override void OnStop()
{
workTimer.Dispose();
base.OnStop();
}
private void DoWork(object state)
{
RunScheduledTasks(); // Do some work
}
}
Simple!
Note that the Timer type being used is System.Threading.Timer, same as Justin specifies.
Use a System.Threading.Timer to fire the process off at the scheduled interval.