I am trying to make a thread safe method. I have this code to test it.
private static readonly Object objLock = new Object();
static void Main(string[] args)
{
// Create ten new threads.
for (int i = 0; i < 10; i++)
{
ThreadStart start = new ThreadStart(LockTest);
new Thread(start).Start();
}
Console.Read();
}
public static void LockTest()
{
lock (objLock)
{
Thread.Sleep(1000);
Console.WriteLine(TimeSpan.FromMilliseconds(Environment.TickCount).Seconds.ToString());
}
}
This works but what I would like to do is if the Lock is in place I need the other threads to exit rather than wait and execute the code when the lock is freed. Is this possible? Thanks.
You should use the Monitor Class which gives you more functionality than the lock. It's basically the same for standard lock usages.
Use the TryEnter function to see if you can acquire the lock. If not, then just exit the thread. Don't forget to release the lock manually though.
Actually, the lock (objLock) { ...} wird be converted into
Monitor.Enter(objLock );
try
{
...
}
finally
{
Monitor.Exit(objLock);
}
Probably you can use the Monitor.TryEnter(objLock, TimeSpan.Zero) instead of Monitor.Enter(objLock) to try get the lock without waiting.
I didn't use TimeSpan.Zero with Monitor before, so try it first.
Related
Have those two code blocks the same effect when looking at the console?
Please note: Currently I am still using and bound to .NET 3.5.
First:
for(int i = 0; i<3;i++)
{
Console.WriteLine(i);
}
Second:
class Worker
{
static int i = 0;
static ManualResetEvent manualResetEvent = new ManualResetEvent(false);
static Object locky = new Object();
static void Work(Object workItem)
{
WaitHandle[] wait = new [] { manualResetEvent };
while (WaitHandle.WaitAny(wait))
{
lock (locky)
{
Console.WriteLine(i++);
}
}
}
}
// main:
Thread thread = new Thread(Worker.Work);
thread.Start();
for (int i=0;i<3;i++)
{
Worker.manualResetEvent.Set();
}
Will the waitHandle increase with every signal? Will the loop run until all signals are done?
Or will a signal be ignored when the thread is already working?
Can someone please bring some light into this?
Since you're using a ManualResetEvent, once you signal the event, it remains signaled until it's reset. Which means setting it once or three times will have the same effect.
This also means that the worker will go into an infinite loop because the event is never reset.
Also, you can't lock on value types. If you could, the int would be boxed and create a new object every time you lock on it - which means you'd be locking on a different object every single time, rendering the lock useless.
I have a multi-threaded program (C#) where I have to share global static variables between threads that may take some time to execute (sending data request to another system using WCF). The problem is that using the lock statement does not seem to guarantee mutual exclusion when it's declared outside of the ThreadPool.
static void Main(string[] args)
{
public static int globalVar = 0;
public object locker;
System.Timers.Timer timer1 = new System.Timers.Timer(1000);
timer1.Elapsed += new ElapsedEventHandler(onTimer1ElapsedEvent);
timer1.Interval = 1000;
timer1.Enabled = true;
System.Timers.Timer timer2 = new System.Timers.Timer(500);
timer2.Elapsed += new ElapsedEventHandler(onTimer2ElapsedEvent);
timer2.Interval = 500;
timer2.Enabled = true;
}
public void onTimer1ElapsedEvent(object source, ElapsedEventArgs e)
{
lock (locker) {
ThreadPool.QueueUserWorkItem(new WaitCallback(state =>
{
globalVar = 1;
Console.WriteLine("Timer1 var = {0}", globalVar);
}));
}
}
public void onTimer2ElapsedEvent(object source, ElapsedEventArgs e)
{
lock (locker) {
ThreadPool.QueueUserWorkItem(new WaitCallback(state =>
{
globalVar = 2;
Thread.Sleep(2000); // simulates a WCF request that may take time
Console.WriteLine("Timer2 var = {0}", globalVar);
}));
}
}
So the lock does not work and the program can prints: Timer2 var = 1
Putting the the lock statement inside the ThreadPool seems to resolve the problem.
public void onTimer1ElapsedEvent(object source, ElapsedEventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(state =>
{
lock (locker) {
globalVar = 1;
Console.WriteLine("Timer1 var = {0}", globalVar);
}
}));
}
public void onTimer2ElapsedEvent(object source, ElapsedEventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(state =>
{
lock (locker) {
globalVar = 2;
Thread.Sleep(2000); // simulates a WCF request that may take time
Console.WriteLine("Timer2 var = {0}", globalVar);
}
}));
}
However, I don't uderstand the difference between the two approaches and why it does not produce the same behaviour.
Also, the 2nd approach resolves the mutual exclusion problem but the timer1 thread will always have to wait for the timer2 to finish his lock statement (which takes time), so the multi-threading concept does not work anymore in my program. I want to know what's the best solution of having multi threading doing their job in parallel with using shared variables ?
You don't need a lock to update variables like that. For example, you can replace this:
lock (locker)
{
globalVar = 1;
Console.WriteLine("Timer1 var = {0}", globalVar);
}
with:
int val = 1;
globalVar = val;
Console.WriteLine("Timer1 var = {0}", val);
Writes to primitive types are guaranteed to be atomic, so there's no need to lock here.
Now, if you want to increment a value, you can write:
int val = Interlocked.Increment(ref globalVar);
You can also add:
int val = Interlocked.Add(ref globalVar, 100);
Again, these don't need locks.
Check out the Interlocked class.
In your first scenario, all you're locking on is the additional of a new WaitCallback onto the ThreadPool. Think of the ThreadPool as a line: all you've done is lock on putting someone else in line (which ironically is actually double work since the ThreadPool itself locks on an internal queue that it maintains). The code that the ThreadPool executes afterwards is on a different thread, happens at a different time, and has nothing to do with that lock anymore.
In your second scenario, the lock is actually in the code that the ThreadPool thread is executing, which is why you're seeing the locking semantics that are expected.
In general, however, I'd recommend against locking in a ThreadPool thread if you can avoid it. The ThreadPool should be used (ideally) for quick running tasks. It depends on the nature and use of the shared state, and what you're trying to accomplish, but in general I'd opt for using Tasks and/or PLINQ when possible.
The shorter and more sensible solution is not to use (yet another) extra thread to execute the Timer. System.Timers.Timer already allocates a pool thread.
public void onTimer1ElapsedEvent(object source, ElapsedEventArgs e)
{
lock (locker) {
globalVar = 1;
Console.WriteLine("Timer1 var = {0}", globalVar);
}
}
public void onTimer2ElapsedEvent(object source, ElapsedEventArgs e)
{
lock (locker) {
globalVar = 2;
Thread.Sleep(2000); // simulates a WCF request that may take time
Console.WriteLine("Timer2 var = {0}", globalVar);
}
}
Your confusion comes from formulations like "Putting the the lock statement inside the ThreadPool".
You put lock statements inside methods to control the threads they are run on.
In process of developing I often face with the next problem: if some method is already executed by one thread - method is must not be executed by another thread. Another thread must do nothing - simple exit from method, beacuse of it I can't use "lock". Usually, I solve this problem like that:
private bool _isSomeMethodExecuted = false;
public void SomeMethod ()
{
if (!this._isSomeMethodExecuted) //check if method is already executed
{
this._isSomeMethodExecuted = true;
//Main code of method
this._isSomeMethodExecuted = false;
}
}
But this code is not thread-safe: if one thread execute condition statement but It be stopped before set flag in true and another thread can execute condition - then both threads are inside method code.
Is there any thread-safe replace for it?
the following is thread-safe and does not block if the method is already executing - even if it is alreasy executing on the same thread... which provides protection from reentrancy for all scenarios.
private long _isSomeMethodExecuted = 0;
public void SomeMethod ()
{
if (Interlocked.Increment (ref this._isSomeMethodExecuted) == 1) //check if method is already executed
{
//Main code of method
}
Interlocked.Decrement (ref this._isSomeMethodExecuted);
}
For refrences see http://msdn.microsoft.com/en-us/library/zs86dyzy.aspx
Monitor does this job for you, but the lock is thread-wide (and therefore open for recursive calls!). The lock statement uses a Monitor too (using the blocking Enter method), but you may work with the TryEnter method instead:
if(Monitor.TryEnter(myLockObject))
{
try
{
DoSomething(); // main code
}
finally
{
Monitor.Exit(myLockObject);
}
}
TryEnter does not block but returns a bool indicating whether the lock was successfully acquired or not.
If you want recursive calls not to enter the main code block again, you should use a semaphore instead. Semaphores use counters instead of locking objects, so you cannot reenter even from the same thread:
class Program
{
private static Semaphore sem = new Semaphore(1, 1);
static void Main(string[] args)
{
MyMethod();
MyMethod();
}
private static void MyMethod()
{
if(sem.WaitOne(0))
{
try
{
Console.WriteLine("Entered.");
MyMethod(); // recursive calls won't re-enter
}
finally
{
sem.Release();
}
}
else
{
Console.WriteLine("Not entered.");
}
}
}
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
}
Problem statement
I have a worker thread that basically scans a folder, going into the files within it, and then sleeps for a while. The scanning operation might take 2-3 seconds but not much more. I'm looking for a way to stop this thread elegantly.
Clarification: I want to stop the thread while it's sleeping, and not while it's scanning. However, the problem is that I do not know what is the current state of the thread. If it's sleeping I want it to exit immediately. If it's scanning, I want it to exit the moment it tries to block.
Attempts at a solution
At first I was using Sleep and Interrupt. Then I found out that Interrupt doesn't really interrupt the Sleep - it only works when the threads TRIES to go into sleeping.
So I switched to Monitor Wait&Pulse. Then I found out that the Pulse only works when I'm actually in the Wait. So now I have a thread which looks like that:
while (m_shouldRun)
{
try
{
DoSomethingThatTakesSeveralSeconds();
lock (this)
{
Monitor.Wait(this, 5000);
}
}
catch (ThreadInterruptedException)
{
m_shouldRun = false;
}
}
And now I need to craft my Stop function. So I started with:
public void Stop()
{
m_shouldRun = false;
lock (this)
{
Monitor.Pulse(this);
}
thread.Join();
}
But this doesn't work because I may be pulsing while the thread works (while it's not waiting). So I added Interrupt:
public void Stop()
{
m_shouldRun = false;
thread.Interrupt();
lock (this)
{
Monitor.Pulse(this);
}
thread.Join();
}
Another option is to use:
public void Stop()
{
m_shouldRun = false;
while (!thread.Join(1000))
{
lock (this)
{
Monitor.Pulse(this);
}
}
}
The question
What is the preferred method? Is there a third method which is preferable?
Another alternative is to use events:
private ManualResetEvent _event = new ManualResetEvent(false);
public void Run()
{
while (true)
{
DoSomethingThatTakesSeveralSeconds();
if (_event.WaitOne(timeout))
break;
}
}
public void Stop()
{
_event.Set();
thread.Join();
}
The way to stop a thread elegantly is to leave it finish by itself. So inside the worker method you could have a boolean variable which will check whether we want to interrupt. By default it will be set to false and when you set it to true from the main thread it will simply stop the scanning operation by breaking from the processing loop.
I recommend to keep it simple:
while (m_shouldRun)
{
DoSomethingThatTakesSeveralSeconds();
for (int i = 0; i < 5; i++) // example: 5 seconds sleep
{
if (!m_shouldRun)
break;
Thread.Sleep(1000);
}
}
public void Stop()
{
m_shouldRun = false;
// maybe thread.Join();
}
This has the following advantages:
It smells like busy waiting, but it's not. $NUMBER_OF_SECONDS checks are done during the waiting phase, which is not comparable to the thousands of checks done in real busy waiting.
It's simple, which greatly reduces the risk of error in multi-threaded code. All your Stop method needs to do is to set m_shouldRun to false and (maybe) call Thread.Join (if it is necessary for the thread to finish before Stop is left). No synchronization primitives are needed (except for marking m_shouldRun as volatile).
I came up with separately scheduling the task:
using System;
using System.Threading;
namespace ProjectEuler
{
class Program
{
//const double cycleIntervalMilliseconds = 10 * 60 * 1000;
const double cycleIntervalMilliseconds = 5 * 1000;
static readonly System.Timers.Timer scanTimer =
new System.Timers.Timer(cycleIntervalMilliseconds);
static bool scanningEnabled = true;
static readonly ManualResetEvent scanFinished =
new ManualResetEvent(true);
static void Main(string[] args)
{
scanTimer.Elapsed +=
new System.Timers.ElapsedEventHandler(scanTimer_Elapsed);
scanTimer.Enabled = true;
Console.ReadLine();
scanningEnabled = false;
scanFinished.WaitOne();
}
static void scanTimer_Elapsed(object sender,
System.Timers.ElapsedEventArgs e)
{
scanFinished.Reset();
scanTimer.Enabled = false;
if (scanningEnabled)
{
try
{
Console.WriteLine("Processing");
Thread.Sleep(5000);
Console.WriteLine("Finished");
}
finally
{
scanTimer.Enabled = scanningEnabled;
scanFinished.Set();
}
}
}
}
}