I implement a class with singleton like this
public static SingleToneClass Instance
{
get
{
return Lazy.Value;
}
}
private static readonly Lazy<SingleToneClass > Lazy = new Lazy<SingleToneClass >(() => new RABTProxy());
within SingleToneClass there's a System.Timers timer
while trying to access the class from different threads the timer suddenly stop
any idea how to fix something like this , this is a sample of what am testing
class Program
{
static void Main(string[] args)
{
//now create a timer each ten seconds create for create
var mainTimer = new Timer
{
Interval = 100
};
mainTimer.Elapsed += (sender, eventArgs) =>
{
Task.Factory.StartNew(() =>
{
while (true)
{
SingleToneClass.Instance.DoWwork();
Thread.Sleep(10);
}
});
};
mainTimer.Start();
Console.ReadLine();
}
}
is it a good idea to use a timer in Singleton,any alternative
Your comment says a timer every ten seconds but you're actually getting one ten times a second.
You then spawn new tasks on the thread pool that will run forever and will block with Thread.Sleep(). This will use all your thread pool threads and it will have to create new ones. BAD!
If all you want is for the DoWork to be called periodically you should skip the timer and launch a single task.
Task.Factory.StartNew(async () =>
{
while (true)
{
SingleToneClass.Instance.DoWwork();
await Task.Delay(TimeSpan.FromSeconds(10));
}
});
Use Microsoft's Reactive Framework (aka Rx) - just NuGet System.Reactive and add using System.Reactive.Linq;.
Then do this:
Observable
.Interval(TimeSpan.FromMilliseconds(10.0))
.Subscribe(_ => SingleToneClass.Instance.DoWwork());
Related
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);
I have 2 sets of jobs that need to be performed separately and can't run parallel. The jobs involve web communication so async is used.
Currently, I have System.Windows.Forms.Timers set up to execute the batches with Task.Run(). To avoid the possible simultaneous execution, first I thought I can simply use a lock() {} inside the timers' Tick (I update the UI with countdown at ticks). Then realized that I need to .Wait() for the task to finish, otherwise it just exits the critical section.
Then I realized that all of this is running on the UI thread, so it's like those Elmer Fudd scenes where he points his rifle in one hole and the end comes out another pointing back at him.
Is there a simple nail-hammer approach to not block the UI thread while maintaining mutually excluded execution?
Here's a sample for one of the timers:
_timer = new Timer { Interval = 1000 };
_timer.Tick += (sender, args) =>
{
var timeSpan = _nextRun - DateTime.Now;
if (timeSpan.Seconds >= 0)
{
UpdateCountdownMessage(string.Format("{0:00}:{1:00}:{2:00} to next run.", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds));
}
else
{
lock (_runLock)
{
Task.Run(() => RunJobs(_batch1Jobs)).Wait();
}
}
};
To make it clearer, there is a 2nd timer, lets say it's called _timer2, that similarly updates a different countdown and runs _batch2Jobs when it reaches 0.
First you need to get rid of lock and switch to SemaphoreSlim
SemaphoreSlim _runLock = new SemaphoreSlim(1, 1);
Then you can use something like this
_timer.Tick += async (sender, args) =>
{
var timeSpan = _nextRun - DateTime.Now;
if (timeSpan.Seconds >= 0)
{
UpdateCountdownMessage(string.Format("{0:00}:{1:00}:{2:00} to next run.", timeSpan.Hours, timeSpan.Minutes, timeSpan.Seconds));
}
else
{
_timer.Enabled = false;
try
{
await Task.Run(async () =>
{
await _runLock.WaitAsync();
try { RunJobs(_batch1Jobs); }
finally { _runLock.Release(); }
});
}
finally { _timer.Enabled = true; }
}
};
Please note that you should never use lock or Task.Wait on the UI thread for a long running tasks. The UI code should use only async/await constructs.
You should use tasks:
Task T1 = Task.Factory.StartNew(() => {/*do work */});
Task T2 = T1.ContinueWith((antecedent) => {/*do work 2*/});
I want to run a process every one minute, but I have been told that the Timer is working every x minute + the time required for the process to finish. but I want the thread to work every 1 minute even though the thread process may keep working for 1 hour.
I hope you got me, so in the final image, I may have 10 threads working together.
is that possible ?
Depends on the timer. Simple test shows that System.Threading.Timer works the way you want:
var timer = new Timer(s => { "Start".Dump(); Thread.Sleep(10000); "Hi!".Dump(); },
null, 1000, 1000);
Thread.Sleep(20000);
timer.Dump();
The callback executes every second even though it takes ten seconds to execute.
This is basically because the callback for this particular timer is simply posted to the threadpool, while e.g. System.Windows.Forms.Timer is actually tied to the UI thread. Of course, if you simply start a new thread (or queue work, or start a new task etc.) in the callback of winforms timer, it will work in a similar (albeit less precise) way.
Using the right tool for the job usually makes things much easier :)
Create a Timer and on the elapse event just fire a new thread to do the work, like the below example:
public class Example
{
private static Timer aTimer;
public static void Main()
{
// Create a timer with a two second interval.
aTimer = new Timer(2000);
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += OnTimedEvent;
aTimer.Enabled = true;
Console.WriteLine("Press the Enter key to exit the program... ");
Console.ReadLine();
Console.WriteLine("Terminating the application...");
}
public static void DoWork()
{
var workCounter = 0;
while (workCounter < 100)
{
Console.WriteLine("Alpha.Beta is running in its own thread." + Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(1000);
workCounter++;
}
}
private static void OnTimedEvent(Object source, ElapsedEventArgs e)
{
// Create the thread object, passing in the method
// via a delegate.
var oThread = new Thread(DoWork);
// Start the thread
oThread.Start();
}
}
Since .NET 4.0 Tasks are preferred to Threads.
The overhead of Task management is minimal.
// Create a task spawning a working task every 1000 msec
var t = Task.Run(async delegate
{
while (isRunning)
{
await Task.Delay(1000);
Task.Run(() =>
{
//your work
};
}
});
I have a timer calling a function every 15 minutes, this function counts the amount of lines in my DGV and starts a thread for each lines (of yet another function), said thread parse a web page which can take anywhere from 1 second to 10 second to finish.
Whilst it does work fine as it is with 1-6 rows, anymore will cause the requests to time-out.
I want it to wait for the newly created thread to finish processing before getting back in the loop to create another thread without locking the main UI
for (int x = 0; x <= dataGridFollow.Rows.Count - 1; x++)
{
string getID = dataGridFollow.Rows[x].Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
Thread t = new Thread(new ParameterizedThreadStart(UpdateLo));
t.Start(ID);
// <- Wait for thread to finish here before getting back in the for loop
}
I have googled a lot in the past 24 hours, read a lot about this specific issue and its implementations (Thread.Join, ThreadPools, Queuing, and even SmartThreadPool).
It's likely that I've read the correct answer somewhere but I'm not at ease enough with C# to decypher those Threading tools
Thanks for your time
to avoid the UI freeze the framework provide a class expressly for these purposes: have a look at the BackgroundWorker class (executes an operation on a separate thread), here's some infos : http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
http://msdn.microsoft.com/en-us/magazine/cc300429.aspx
Btw looks if I understand correctly you don't want to parallelize any operation so just wait for the method parsing the page to be completed. Basically for each (foreach look) row of your grid you get the id and call the method. If you want to go parallel just reuse the same foreach loop and add make it Parallel
http://msdn.microsoft.com/en-us/library/dd460720.aspx
What you want is to set off a few workers that do some task.
When one finishes you can start a new one off.
I'm sure there is a better way using thread pools or whatever.. but I was bored so i came up with this.
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Threading;
namespace WorkerTest
{
class Program
{
static void Main(string[] args)
{
WorkerGroup workerGroup = new WorkerGroup();
Console.WriteLine("Starting...");
for (int i = 0; i < 100; i++)
{
var work = new Action(() =>
{
Thread.Sleep(1000); //somework
});
workerGroup.AddWork(work);
}
while (workerGroup.WorkCount > 0)
{
Console.WriteLine(workerGroup.WorkCount);
Thread.Sleep(1000);
}
Console.WriteLine("Fin");
Console.ReadLine();
}
}
public class WorkerGroup
{
private List<Worker> workers;
private Queue<Action> workToDo;
private object Lock = new object();
public int WorkCount { get { return workToDo.Count; } }
public WorkerGroup()
{
workers = new List<Worker>();
workers.Add(new Worker());
workers.Add(new Worker());
foreach (var w in workers)
{
w.WorkCompleted += (OnWorkCompleted);
}
workToDo = new Queue<Action>();
}
private void OnWorkCompleted(object sender, EventArgs e)
{
FindWork();
}
public void AddWork(Action work)
{
workToDo.Enqueue(work);
FindWork();
}
private void FindWork()
{
lock (Lock)
{
if (workToDo.Count > 0)
{
var availableWorker = workers.FirstOrDefault(x => !x.IsBusy);
if (availableWorker != null)
{
var work = workToDo.Dequeue();
availableWorker.StartWork(work);
}
}
}
}
}
public class Worker
{
private BackgroundWorker worker;
private Action work;
public bool IsBusy { get { return worker.IsBusy; } }
public event EventHandler WorkCompleted;
public Worker()
{
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(OnWorkerDoWork);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(OnWorkerRunWorkerCompleted);
}
private void OnWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (WorkCompleted != null)
{
WorkCompleted(this, EventArgs.Empty);
}
}
public void StartWork(Action work)
{
if (!IsBusy)
{
this.work = work;
worker.RunWorkerAsync();
}
else
{
throw new InvalidOperationException("Worker is busy");
}
}
private void OnWorkerDoWork(object sender, DoWorkEventArgs e)
{
work.Invoke();
work = null;
}
}
}
This would be just a starting point.
You could start it off with a list of Actions and then have a completed event for when that group of actions is finished.
then at least you can use a ManualResetEvent to wait for the completed event.. or whatever logic you want really.
Call a method directly or do a while loop (with sleep calls) to check the status of the thread.
There are also async events but the would call another method, and you want to continue from the same point.
I have no idea why the requests would timeout. That sounds like a different issue. However, I can make a few suggestions regarding your current approach.
Avoid creating threads in loops with nondeterministic bounds. There is a lot of overhead in creating threads. If the number of operations is not known before hand then use the ThreadPool or the Task Parallel Library instead.
You are not going to get the behavior you want by blocking the UI thread with Thread.Join. The cause the UI to become unresponsive and it will effectively serialize the operations and cancel out any advantage you were hoping to gain with threads.
If you really want to limit the number of concurrent operations then a better solution is to create a separate dedicated thread for kicking off the operations. This thread will spin around a loop indefinitely waiting for items to appear in a queue and when they do it will dequeue them and use that information to kick off an operation asynchronously (again using the ThreadPool or TPL). The dequeueing thread can contain the logic for limiting the number of concurrent operations. Search for information regarding the producer-consumer pattern to get a better understand of how you can implement this.
There is a bit of a learning curve, but who said threading was easy right?
If I understand correctly, what you're currently doing is looping through a list of IDs in the UI thread, starting a new thread to handle each one. The blocking issue you're seeing then could well be that it's taking too many resources to create unique threads. So, personally (without knowing more) would redesign the process like so:
//Somewhere in the UI Thread
Thread worker = new Thread(new ParameterizedThreadStart(UpdateLoWorker));
worker.Start(dataGridFollow.Rows);
//worker thread
private void UpdateLoWorker(DataRowCollection rows)
{
foreach(DataRow r in rows){
string getID = r.Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
UpdateLo(ID);
}
}
Here you'd have a single non-blocking worker which sequentially handles each ID.
Consider using Asynchronous CTP. It's an asynch pattern Microsoft recently released for download. It should simplify asynch programming tremendouesly. The link is http://msdn.microsoft.com/en-us/vstudio/async.aspx. (Read the whitepaper first)
Your code would look something like the following. (I've not verified my syntax yet, sorry).
private async Task DoTheWork()
{
for(int x = 0; x <= dataGridFollow.Rows.Count - 1; x++)
{
string getID = dataGridFollow.Rows[x].Cells["ID"].Value.ToString();
int ID = int.Parse(getID);
task t = new Task(new Action<object>(UpdateLo), ID);
t.Start();
await t;
}
}
This method returns a Task that can be checked periodically for completion. This follows the pattern of "fire and forget" meaning you just call it and presumably, you don't care when it completes (as long as it does complete before 15 minutes).
EDIT
I corrected the syntax above, you would need to change UpdateLo to take an object instead of an Int.
For a simple background thread runner that will run one thread from a queue at a time you can do something like this:
private List<Thread> mThreads = new List<Thread>();
public static void Main()
{
Thread t = new Thread(ThreadMonitor);
t.IsBackground = true;
t.Start();
}
private static void ThreadMonitor()
{
while (true)
{
foreach (Thread t in mThreads.ToArray())
{
// Runs one thread in the queue and waits for it to finish
t.Start();
mThreads.Remove(t);
t.Join();
}
Thread.Sleep(2000); // Wait before checking for new threads
}
}
// Called from the UI or elsewhere to create any number of new threads to run
public static void DoStuff()
{
Thread t = new Thread(DoCorestuff);
t.IsBackground = true;
mActiveThreads.Add(t);
}
public static void DoStuffCore()
{
// Your code here
}
I'm writing a Windows service that runs a variable length activity at intervals (a database scan and update). I need this task to run frequently, but the code to handle isn't safe to run multiple times concurrently.
How can I most simply set up a timer to run the task every 30 seconds while never overlapping executions? (I'm assuming System.Threading.Timer is the correct timer for this job, but could be mistaken).
You could do it with a Timer, but you would need to have some form of locking on your database scan and update. A simple lock to synchronize may be enough to prevent multiple runs from occurring.
That being said, it might be better to start a timer AFTER your operation is complete, and just use it one time, then stop it. Restart it after your next operation. This would give you 30 seconds (or N seconds) between events, with no chance of overlaps, and no locking.
Example :
System.Threading.Timer timer = null;
timer = new System.Threading.Timer((g) =>
{
Console.WriteLine(1); //do whatever
timer.Change(5000, Timeout.Infinite);
}, null, 0, Timeout.Infinite);
Work immediately .....Finish...wait 5 sec....Work immediately .....Finish...wait 5 sec....
I'd use Monitor.TryEnter in your elapsed code:
if (Monitor.TryEnter(lockobj))
{
try
{
// we got the lock, do your work
}
finally
{
Monitor.Exit(lockobj);
}
}
else
{
// another elapsed has the lock
}
I prefer System.Threading.Timer for things like this, because I don't have to go through the event handling mechanism:
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, 30000);
object updateLock = new object();
void UpdateCallback(object state)
{
if (Monitor.TryEnter(updateLock))
{
try
{
// do stuff here
}
finally
{
Monitor.Exit(updateLock);
}
}
else
{
// previous timer tick took too long.
// so do nothing this time through.
}
}
You can eliminate the need for the lock by making the timer a one-shot and re-starting it after every update:
// Initialize timer as a one-shot
Timer UpdateTimer = new Timer(UpdateCallback, null, 30000, Timeout.Infinite);
void UpdateCallback(object state)
{
// do stuff here
// re-enable the timer
UpdateTimer.Change(30000, Timeout.Infinite);
}
instead of locking (which could cause all of your timed scans to wait and eventually stack up). You could start the scan/update in a thread and then just do a check to see if the thread is still alive.
Thread updateDBThread = new Thread(MyUpdateMethod);
...
private void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if(!updateDBThread.IsAlive)
updateDBThread.Start();
}
Starting from .NET 6 there is a new timer available, the PeriodicTimer. This is a lightweight async-enabled timer, that becomes the perfect tool when overlapping executions should be strictly forbidden. You use this timer by writing an asynchronous method with a loop, and invoking it to start the loop:
private Task _operation;
private CancellationTokenSource _operationCancellation = new();
//...
_operation = StartTimer();
//...
private async Task StartTimer()
{
PeriodicTimer timer = new(TimeSpan.FromSeconds(30));
while (true)
{
await timer.WaitForNextTickAsync(_operationCancellation.Token);
try
{
DoSomething();
}
catch (Exception ex)
{
_logger.LogError(ex);
}
}
}
Instead of using a CancellationTokenSource, you can also stop the loop by disposing the PeriodicTimer. In this case the await timer.WaitForNextTickAsync() will return false.
It is possible that the DoSomething will be invoked subsequently with smaller interval than 30 seconds, but it's impossible that it will be invoked in overlapping fashion, unless you start accidentally two asynchronous loops.
This timer does not support disabling and reenabling it. If you need this functionality you could look at the third-party Nito.AsyncEx.PauseTokenSource component.
In case you are targeting a .NET version earlier than .NET 6, you could look at this question for an alternative: Run async method regularly with specified interval.
You could use the AutoResetEvent as follows:
// Somewhere else in the code
using System;
using System.Threading;
// In the class or whever appropriate
static AutoResetEvent autoEvent = new AutoResetEvent(false);
void MyWorkerThread()
{
while(1)
{
// Wait for work method to signal.
if(autoEvent.WaitOne(30000, false))
{
// Signalled time to quit
return;
}
else
{
// grab a lock
// do the work
// Whatever...
}
}
}
A slightly "smarter" solution is as follow in pseudo-code:
using System;
using System.Diagnostics;
using System.Threading;
// In the class or whever appropriate
static AutoResetEvent autoEvent = new AutoResetEvent(false);
void MyWorkerThread()
{
Stopwatch stopWatch = new Stopwatch();
TimeSpan Second30 = new TimeSpan(0,0,30);
TimeSpan SecondsZero = new TimeSpan(0);
TimeSpan waitTime = Second30 - SecondsZero;
TimeSpan interval;
while(1)
{
// Wait for work method to signal.
if(autoEvent.WaitOne(waitTime, false))
{
// Signalled time to quit
return;
}
else
{
stopWatch.Start();
// grab a lock
// do the work
// Whatever...
stopwatch.stop();
interval = stopwatch.Elapsed;
if (interval < Seconds30)
{
waitTime = Seconds30 - interval;
}
else
{
waitTime = SecondsZero;
}
}
}
}
Either of these has the advantage that you can shutdown the thread, just by signaling the event.
Edit
I should add, that this code makes the assumption that you only have one of these MyWorkerThreads() running, otherwise they would run concurrently.
I've used a mutex when I've wanted single execution:
private void OnMsgTimer(object sender, ElapsedEventArgs args)
{
// mutex creates a single instance in this application
bool wasMutexCreatedNew = false;
using(Mutex onlyOne = new Mutex(true, GetMutexName(), out wasMutexCreatedNew))
{
if (wasMutexCreatedNew)
{
try
{
//<your code here>
}
finally
{
onlyOne.ReleaseMutex();
}
}
}
}
Sorry I'm so late...You will need to provide the mutex name as part of the GetMutexName() method call.