I'm working on the below code and am trying to make it as fast as it can be.
Basically the execute method gets called every time an event gets triggered in the system. What I am testing for is to see whether x number of minutes have passed since a reduce was last performed. If x number of minutes have passed then we should execute the task.
Since the events can be triggered from any thread and happen quite quickly, I thought that triggering the task out side of the lock (even though its a task) would be better than having it in the lock.
Does anyone have any feedback on how this can be improved?
public class TriggerReduce
{
private readonly object _lock = new object();
private readonly int _autoReduceInterval = 5;
private DateTime _lastTriggered;
public void Execute(object sender, EventArgs e)
{
var currentTime = DateTime.Now;
if (currentTime.Subtract(_lastTriggered).Duration().TotalMinutes > _autoReduceInterval)
{
var shouldRun = false;
lock (_lock)
{
if (currentTime.Subtract(_lastTriggered).Duration().TotalMinutes > _autoReduceInterval)
{
_lastTriggered = currentTime;
shouldRun = true;
}
}
if (shouldRun)
{
Task.Factory.StartNew(() =>
{
//Trigger reduce which is a long running task
}, TaskCreationOptions.LongRunning);
}
}
}
}
Oh, I wouldn't do that! Put the 'if (currentTime' and the 'shouldRun' stuff back inside the lock.
Don't change/check state outside a lock - it's sure to screw up.
In this case, a thread that has just set 'shouldRun' to true may have its decision reversed by another thread that enters and sets 'shouldRun' to false again before getting stuck on the lock. The first thread then does not get to the 'StartNew' and the later thread won't either because the first thread set the _lastTriggered to the current time.
OTOH :) since 'shouldRun' is an auto varaible and not a field, it is not state. Only one thread can get inside the lock, double-check the interval and update the _lastTriggered time.
I don't like this kind of double-check but, at the moment, can't see why it would not work.
Would it be helpful to avoid the lock and use Interlocked.Exchange instead?
E.g.
private long _lastTriggeredTicks;
private DateTime lastTriggered
{
get
{
var l = Interlocked.Read( ref _lastTriggeredTicks );
return new DateTime( l );
}
set
{
Interlocked.Exchange( ref _lastTriggeredTicks, value );
}
}
From what I understand Interlocked is faster than a lock statement.
public class TriggerReduce //StartNew is fast and returns fast
{
private readonly object _lock = new object();
private readonly int _triggerIntervalMins = 5;
private DateTime _nextTriggerAt = DateTime.MinValue;
private bool inTrigger = false;
public void Execute(object sender, EventArgs e)
{
lock (_lock)
{
var currentTime = DateTime.Now;
if (_nextTriggerAt > currentTime)
return;
_nextTriggerAt = currentTime.AddMinutes(_triggerIntervalMins);//runs X mins after last task started running (or longer if task took longer than X mins)
}
Task.Factory.StartNew(() =>
{
//Trigger reduce which is a long running task
}, TaskCreationOptions.LongRunning);
}
}
public class TriggerReduce//startNew is a long running function that you want to wait before you recalculate next execution time
{
private readonly object _lock = new object();
private readonly int _triggerIntervalMins = 5;
private DateTime _nextTriggerAt = DateTime.MinValue;
private bool inTrigger = false;
public void Execute(object sender, EventArgs e)
{
var currentTime;
lock (_lock)
{
currentTime = DateTime.Now;
if (inTrigger || (_nextTriggerAt > currentTime))
return;
inTrigger = true;
}
Task.Factory.StartNew(() =>
{
//Trigger reduce which is a long running task
}, TaskCreationOptions.LongRunning);
lock (_lock)
{
inTrigger = false;
_nextTriggerAt = DateTime.Now.AddMinutes(_triggerIntervalMins);//runs X mins after task finishes
//_nextTriggerAt = currentTime.AddMinutes(_triggerIntervalMins);//runs X mins after last task started running (or longer if task took longer than X mins)
}
}
}
Use Monitor.TryEnter.
if (Monitor.TryEnter(_lock))
{
try
{
if (currentTime.Subtract(_lastTriggered).Duration().TotalMinutes >
_autoReduceInterval)
{
_lastTriggered = currentTime;
shouldRun = true;
}
}
finally
{
Monitor.Exit(_lock);
}
}
I think you already have a fairly reasonable approach. The big problem is that you are accessing _lastTriggered outside of the lock. The double-checked locking idiom is not going to work here. Simply your code so that it looks like this.
public void Execute(object sender, EventArgs e)
{
var currentTime = DateTime.Now;
var shouldRun = false;
lock (_lock)
{
TimeSpan span = currentTime - _lastTriggeed;
if (span.TotalMinutes > _autoReduceInterval)
{
_lastTriggered = currentTime;
shouldRun = true;
}
}
if (shouldRun)
{
Task.Factory.StartNew(() =>
{
//Trigger reduce which is a long running task
}, TaskCreationOptions.LongRunning);
}
}
Related
I have a method that checks whether some timeout period has expired, and if it has, resets the start time and returns true:
bool CheckAndResetTimeout() {
if (DateTime.UtcNow > _start + _timeout) {
_start = DateTime.UtcNow;
return true;
}
return false;
}
How can I make this thread safe in the sense that if 2 threads hit it at the same time, it is guaranteed to only return true once? I think this can be achieved via double-check locking, but I was hoping to find something in the BCLs (under System.Threading most likely) that might provide a higher-level abstraction for this.
You can use the lock keyword for this:
static object TimerLock = new object();
static bool CheckAndResetTimeout()
{
lock (TimerLock)
{
if (DateTime.UtcNow > _start + _timeout)
{
_start = DateTime.UtcNow;
return true;
}
return false;
}
}
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement
I hoped to avoid a lock if possible, such as by composing lighter-weight constructs from Sysetm.Threading.Interlocked, but I haven't come up with a good way to do that. So for now I'm doing double-checked locking, which at least avoids the lock overhead most of the time.
private readonly object _timeoutLock = new object();
public bool CheckAndResetTimeout() {
if (DateTime.UtcNow > _start + _timeout) {
lock (_timeoutLock) {
if (DateTime.UtcNow > _start + _timeout) {
_start = DateTime.UtcNow;
return true;
}
}
}
return false;
}
I have the following code:
private DateTime lastUploadActivityTime = DateTime.Now;
private void HttpSendProgress(object sender, HttpProgressEventArgs e)
{
// update variable
lastUploadActivityTime = DateTime.Now;
......
boolThreadAvailableTargetSiteActive = false;
}
// this method is executed in different thread, than method above
private void ThreadCheckAvailableTargetSite()
{
while (boolThreadAvailableTargetSiteActive)
{
if (lastUploadActivityTime.AddSeconds(5) <= DateTime.Now)
{
MessageBox.Show("BREAK");
boolThreadAvailableTargetSiteActive = false;
}
Thread.Sleep(500);
}
}
I need to block the variable lastUploadActivityTime in first method (during lastUploadActivityTime = DateTime.Now;) to prevent read lastUploadActivityTime in second method (lastUploadActivityTime.AddSeconds(5) <= DateTime.Now). How can I do it? Does Mutex help me to prevent reading variable?
The lock keyword ensures that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released. Best practice is to define a private object to lock on, or a private static object variable to protect data common to all instances.
private object syncLock = new object();
private DateTime lastUploadActivityTime = DateTime.Now;
private void HttpSendProgress(object sender, HttpProgressEventArgs e)
{
// update variable
lock (syncLock)
{
lastUploadActivityTime = DateTime.Now;
}
}
// this method is executed in different thread, than method above
private void ThreadCheckAvailableTargetSite()
{
while (boolThreadAvailableTargetSiteActive)
{
lock (syncLock)
{
if (lastUploadActivityTime.AddSeconds(5) <= DateTime.Now)
{
MessageBox.Show("BREAK");
boolThreadAvailableTargetSiteActive = false;
}
}
Thread.Sleep(500);
}
}
mutex would be overkill, use lock instead in both methods to syncronize read
http://msdn.microsoft.com/en-us/library/c5kehkcz.aspx
I'm writing an app, that performs very long requests at background. After each request I need to send result to main form.
So, here is a code:
Form1.cs
private async void StartButton_Click(object sender, EventArgs e)
{
await Logic.GenerateStackAsync(stackSettings, delegate(FullOrder transaction)
{
lastOrderId.Text = transaction.OrderId;
}
);
MessageBox.Show("Completed!");
}
Logic.cs:
public static bool GenerateStack(StackSettings stackSettings, Action<FullOrder> onOrderCreated = null)
{
for(var i = 0; i < 10; i++)
{
// long, long request, replaced with:
System.Threading.Thread.Sleep(10000);
if (onOrderCreated != null)
{
onOrderCreated.Invoke(order);
// tried to change it with onOrderCreated(order), no results.
}
}
return true;
}
public static Task<bool> GenerateStackAsync(StackSettings stackSettings, Action<FullOrder> onOrderCreated)
{
return TaskEx.Run(() => GenerateStack(stackSettings, onOrderCreated));
}
It throws an exception: "Control 'lastOrderId' accessed from a thread other than the thread it was created on.", which can be fixed by adding CheckForIllegalCrossThreadCalls = false;, but I think that this is a bad experience. How make it right? Thank you in advance.
P.S. Sorry for bad English.
First, do not expose (fake-)asynchronous wrappers for your synchronous methods.
Next, if you want to report progress updates, then use the progress update classes provided in .NET for that purpose.
public static bool GenerateStack(StackSettings stackSettings, IProgress<FullOrder> progress = null)
{
for(var i = 0; i < 10; i++)
{
// long, long request, replaced with:
System.Threading.Thread.Sleep(10000);
if (progress != null)
{
progress.Report(order);
}
}
return true;
}
Then, you can call it as such:
private async void StartButton_Click(object sender, EventArgs e)
{
var progress = new Progress<FullOrder>(transaction =>
{
lastOrderId.Text = transaction.OrderId;
});
await Task.Run(() => Logic.GenerateStack(stackSettings, progress));
MessageBox.Show("Completed!");
}
I would say that you need to use Control.Invoke to solve that problem:
See http://msdn.microsoft.com/library/system.windows.forms.control.invoke(v=vs.110).aspx
when you use async\await u actually starting new thread you do you stuff there and you want the result to show in the main thread the UIThread thats why you need to use the Control.Invoke
I have the following code that starts some threads:
List<Stuff> lNewStuff = new List<Stuff>();
// populate lNewStuff
for (int i = 0; i < accounts.Length; i++)
{
Account aTemp = _lAccounts.Find(item => item.ID == accounts[i]);
Thread tTemp = new Thread(() => aTemp.ExecuteMe(lNewStuff));
tTemp.Start();
}
Then in the Account class you have the ExecuteMe method that has a lock:
public class Account
{
private Object lockThis = new Object();
public void ExecuteMe(List<Stuff> lNewStuff)
{
//Ensure only one thread at a time can run this code
lock (lockThis)
{
//main code processing
}
}
}
Now, sometimes the thread starts with lNewStuff == null since it sometimes does not find any New Stuff with the Account ID. This is normal for this project. The thread should always try to run but when null I want this thread to die and not wait when a lock is encountered.
So specifically:
If lNewStuff is null and there is a lock then terminate the thread. (how to do this?)
If lNewStuff is null and there is no lock then run normally (does this already)
If lNewStuff is not null and there is a lock then wait for the lock to finish (does this already)
if lNewStuff is not null and there is no lock then run normally (does this already)
When lNewStuff is null you could use Monitor.TryEnter and only continue if the lock is granted:
public class Account
{
private readonly object lockThis = new object();
public void ExecuteMe(List<Stuff> lNewStuff)
{
bool lockTaken = false;
try
{
if (lNewStuff == null)
{
// non-blocking - only takes the lock if it's available
Monitor.TryEnter(lockThis, ref lockTaken);
}
else
{
// blocking - equivalent to the standard lock statement
Monitor.Enter(lockThis, ref lockTaken);
}
if (lockTaken)
{
// main code processing
}
}
finally
{
if (lockTaken)
{
Monitor.Exit(lockThis);
}
}
}
}
If lNewStuff is null and there is a lock then terminate the thread. (how to do this?) ,
do you want to still start a thread if lNewStuff is Null if answer is no then solution must be very simple.
List<Stuff> lNewStuff = new List<Stuff>();
// populate lNewStuff
for (int i = 0; i < accounts.Length; i++)
{
Account aTemp = _lAccounts.Find(item => item.ID == accounts[i]);
if(lNewStuff!=null)
{
Thread tTemp = new Thread(() => aTemp.ExecuteMe(lNewStuff));
tTemp.Start();
}
}
also you shd create a single lock object
private Object lockThis = new Object(); // this statement is creating new lock object with every account object, and hence does not ensure critical section protection.
Change this to
private static Object lockThis = new Object();
Just to be different:
public class Foo : IDisposable
{
private Semaphore _blocker;
public Foo(int maximumAllowed)
{
_blocker = new Semaphore(1,1);
}
public void Dispose()
{
if(_blocker != null)
{
_blocker.Dispose();
_blocker.Close();
}
}
public void LimitedSpaceAvailableActNow(object id)
{
var gotIn = _blocker.WaitOne(0);
if(!gotIn)
{
Console.WriteLine("ID:{0} - No room!", id);
return;
}
Console.WriteLine("ID:{0} - Got in! Taking a nap...", id);
Thread.Sleep(1000);
_blocker.Release();
}
}
Test rig:
void Main()
{
using(var foo = new Foo(1))
{
Enumerable.Range(0, 10)
.Select(t =>
Tuple.Create(t, new Thread(foo.LimitedSpaceAvailableActNow)))
.ToList()
.AsParallel()
.ForAll(t => t.Item2.Start(t.Item1));
Console.ReadLine();
}
}
Output:
ID:4 - Got in! Taking a nap...
ID:8 - No room!
ID:0 - No room!
ID:7 - No room!
ID:2 - No room!
ID:6 - No room!
ID:5 - No room!
ID:9 - No room!
ID:1 - No room!
ID:3 - No room!
I want to display CPU usage for my multithread application (working over multicore processor). I want to receive numbers close to Task manager's. But I got numbers more than 100%. Even more than 500%. Yes, I know, than counter "% Processor Time" for category "Process" I need to divide into Environment.ProcessorCount or "NumberOfLogicalProcessors" (same for my configuration). And 500% is a result after this operation. I tested this example on different computers with different hardware (i7, i5, Core2) and software configurations (Windows 7 SP1 with all updates, Windows 2008 R2 SP1 with all updates) and got same problem.
public static class SystemInfo
{
private static Process _thisProc;
private static bool HasData = false;
private static PerformanceCounter _processTimeCounter;
private static void Init()
{
if (HasData)
return;
if (CheckForPerformanceCounterCategoryExist("Process"))
{
_processTimeCounter = new PerformanceCounter();
_processTimeCounter.CategoryName = "Process";
_processTimeCounter.CounterName = "% Processor Time";
_processTimeCounter.InstanceName = FindInstanceName("Process");
_processTimeCounter.NextValue();
}
MaximumCpuUsageForCurrentProcess = 0;
HasData = true;
}
private static bool CheckForPerformanceCounterCategoryExist(string categoryName)
{
return PerformanceCounterCategory.Exists(categoryName);
}
public static string FindInstanceName(string categoryName)
{
string result = String.Empty;
_thisProc = Process.GetCurrentProcess();
if (!ReferenceEquals(_thisProc, null))
{
if (!String.IsNullOrEmpty(categoryName))
{
if (CheckForPerformanceCounterCategoryExist(categoryName))
{
PerformanceCounterCategory category = new PerformanceCounterCategory(categoryName);
string[] instances = category.GetInstanceNames();
string processName = _thisProc.ProcessName;
if (instances != null)
{
foreach (string instance in instances)
{
if (instance.ToLower().Equals(processName.ToLower()))
{
result = instance;
break;
}
}
}
}
}
}
return result;
}
public static int CpuUsageForCurrentProcess
{
get
{
Init();
if (!ReferenceEquals(_processTimeCounter, null))
{
int result = (int) _processTimeCounter.NextValue();
result /= Environment.ProcessorCount; //NumberOfLogicalProcessors //same for me
if (MaximumCpuUsageForCurrentProcess < result)
MaximumCpuUsageForCurrentProcess = result;
return result;
}
return 0;
}
}
public static int MaximumCpuUsageForCurrentProcess { private set; get; }
}
and code to execute (you need to create windows forms application with two labeles, one BackgroundWorker and one button)
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
IList<Task> tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
Task t = new Task(() =>
{
do {
if (backgroundWorker1.CancellationPending)
break;
} while (true);
});
t.Start();
tasks.Add(t);
}
Task displayProgress = new Task(() => { do {
if (backgroundWorker1.CancellationPending)
break;
backgroundWorker1.ReportProgress(1);
Thread.Sleep(10);
} while (true); });
displayProgress.Start();
tasks.Add(displayProgress);
Task.WaitAll(tasks.ToArray());
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = SystemInfo.CpuUsageForCurrentProcess.ToString();
label2.Text = SystemInfo.MaximumCpuUsageForCurrentProcess.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = SystemInfo.CpuUsageForCurrentProcess.ToString();
if (backgroundWorker1.IsBusy)
backgroundWorker1.CancelAsync();
else
backgroundWorker1.RunWorkerAsync();
}
Please show me my error. And yes, I read this article and noticed that
“\Process(…)\% Processor Time” can go up to N*100 (where N is the number of CPUs) because it adds up the CPU usage of the requested process across all the CPUs.
This (somewhat related) question suggests using the System.Diagnostics.Process.TotalProcessorTime and System.Diagnostics.ProcessThread.TotalProcessorTime properties instead, for low overhead and easy implementation.
(Edit: Here's an article explaining how to use the properties, as well.)
Also, it looks like you're not waiting long enough between calls to "_processTimeCounter.NextValue()." As per the documentation, you're supposed to wait at least 1 second. Not sure if that would cause your strange numbers or not.