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;
}
Related
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 try to synchronize three threads (named "1", "2" and "3") using Semaphore class. They have to print a string into console respecting consequence: 1->2->3. Here is my code:
class MyThread
{
public Thread Thrd;
static Semaphore sem = new Semaphore(1, 1);
static int flag = 1;
public MyThread(string name)
{
Thrd = new Thread(this.Run);
Thrd.Name = name;
Thrd.Start();
}
void Run()
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
}
if (flag == 4)
flag = 1;
Thread.Sleep(300);
sem.Release();
}
}
class SemaphoreDemo
{
static void Main()
{
for (int i = 0; i < 10; i++)
{
MyThread mt1 = new MyThread("1");
MyThread mt2 = new MyThread("2");
MyThread mt3 = new MyThread("3");
mt1.Thrd.Join();
mt2.Thrd.Join();
mt3.Thrd.Join();
}
}
}
But sometimes strings from threads #2 and #3 are not seen. Where is my mistake and how can I fix this problem?
Thank you very much!
The problem is that sometimes a thread will acquire the semaphore out of order, and you don't have any retry logic. Take a look at your Run method.
void Run()
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
}
if (flag == 4)
flag = 1;
Thread.Sleep(300);
sem.Release();
}
Now, what happens if the thread named "3" acquires the semaphore first? flag is equal to 1, so the conditional code won't be executed. The thread will just sleep for 300 milliseconds and then exit. If you want this to work, you have to make the thread retry:
void Run()
{
bool success = false;
while (!success)
{
sem.WaitOne();
if (Convert.ToInt32(Thrd.Name) == flag)
{
Console.WriteLine("Thread " + Thrd.Name);
flag++;
success = true;
}
sem.Release();
if (!success)
{
// let somebody else try
Thread.Sleep(300);
}
}
}
That will make your sample work as expected.
I suspect that this is just an exercise to see how threading and semaphores work. Note, however, that a Mutex is usually more appropriate than a Semaphore with a maximum count of 1.
Note also that there are other ways to make threads execute in sequence, although truthfully if you're going to sequence your threads then you probably don't need more than one thread. Unless those threads are doing other things and they only need to sequence once--or infrequently.
I am implementing a preemptive, exclusive function in a multithreaded environment, where if a cancel request occurs even when the function is not running, when the function does run, it knows about this cancel request and does not run. I came across various different ways to do this in C# using ManualResetEvent and the like(something like the answer to this question Synchronizing a Timers.Timer elapsed method when stopping), however I was wondering if something as simple as what I am doing in the code below would suffice. Are there any inadvertent bugs that I am introducing here?
bool cancel = false;
bool running = false;
object Lock = new object();
void PremptiveExclusiveFunction() {
lock(Lock) {
if(running)
return;
running = true;
}
for(int i=0; i < numIter; i++) {
lock(Lock) {
if(cancel) {
cancel = false;
running = false;
return;
}
}
// iteration code
}
lock(Lock) {
running = false;
}
}
void Stop() {
lock(Lock) {
cancel = true;
}
}
As far as I know, this seems to handle my 3 requirements:
1. ability to preempt
2. exclusivity in time, where this only copy of this function can be running
3. a cancel request not being lost because Stop is called before PreemptiveExclusiveFunction
I'd be grateful if more experienced minds could point out if I am indeed missing something.
Entire function body can be locked to eliminate the running boolean:
object #lock = new object();
volatile bool cancel = false;
void Function () {
if (!Monitor.TryEnter(#lock))
return;
try {
for (var i = 0; i < 100; i++) {
if (cancel) {
cancel = false;
return;
}
// code
}
} finally {
Monitor.Exit(#lock);
}
}
void Stop () {
cancel = true;
}
+ Notice the volatile keyword:
http://msdn.microsoft.com/en-us/library/vstudio/x13ttww7(v=vs.100).aspx
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);
}
}
In my multi threaded web app I invoke in the ThreadPool SomeMethod which can throw an exception. Suppose I want to make a few attempts if it causes an exception at first call. I decide to use System.Timers.Timer inside my action for attempts. Can I use the code below? Is it safely?
static void Caller()
{
ThreadPool.QueueUserWorkItem(action =>
{
try
{
SomeMethod();
Console.WriteLine("Done.");
}
catch
{
var t = new System.Timers.Timer(1000);
t.Start();
var count = 0;
t.Elapsed += new System.Timers.ElapsedEventHandler((o, a) =>
{
var timer = o as System.Timers.Timer;
count++;
var done = false;
Exception exception = null;
try
{
Console.WriteLine(count);
SomeMethod();
done = true;
}
catch (Exception ex)
{
exception = ex;
}
if (done || count == 10)
{
Console.WriteLine(String.Format("Stopped. done: {0}, count: {1}", done, count));
t.Stop();
if (!done) throw exception;
}
});
}
});
Thread.Sleep(100000);
}
static void SomeMethod()
{
var x = 1 / new Random().Next(0, 2);
}
You should Dispose each Timer after use, that's for sure. But, probably you could do something even simpler:
static void Main()
{
ThreadPool.QueueUserWorkItem(action =>
{
while (TrySomeMethod() == false)
Thread.Sleep(1000);
});
// wait here
Console.Read();
}
static bool TrySomeMethod()
{
try
{
SomeMethod();
return true;
}
catch
{
return false;
}
}
I do not think that using a timer in a thread pool thread is a safe approach. I may be wrong, but the timer will raise its elapsed event when the thread method has already been finished to execute. In this case, the exception will be thrown. Also, I do not see that you are not disposing the timer which leads to resource leaks. If you explain why you need the timer, I will try to find a safe solution...
I don't see the point of using a Timer within a ThreadPool queue, because the ThreadPool would spawn a new thread, and the Timer would spawn a new thread as well.
I would just have a loop within that delegate, because it would not block the main thread either way. Groo showed a good example of that.