I have a static class with multiple static methods.
private static Session _session = new Session();
public static void Method1() {
if(_session != null)
_session.Action();
}
public static void Method2() {
if(_session != null)
_session.Action();
}
public static void Method3() {
if(_session != null)
_session.Action();
}
public static void Method4(string path) {
_session.Disconnect();
_session.Connect(new Config(path));
}
Method1, Method2, Method3 are fully thread safe, they can be safely called simultaneously from any number of threads. In fact, for performance reasons, I need to allow multiple threads to call Method1,2,3 concurrently.
The problem is, it is possible for Method1,2,3 to throw an exception when Method4() is being called.
How do I allow multiple threads to call Method1,2,3 while also blocking them when Method4() is being called?
As SLaks has pointed out, a ReadWriterLock was a great solution.
Here is what I ended up implementing:
private static ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
private static Session _session = new Session();
public static void Method1() {
_lock.EnterReadLock();
try {
if(_session != null)
_session.Action();
}
finally
{
_lock.ExitReadLock();
}
}
public static void Method2() {
_lock.EnterReadLock();
try {
if(_session != null)
_session.Action();
}
finally
{
_lock.ExitReadLock();
}
}
public static void Method3() {
_lock.EnterReadLock();
try {
if(_session != null)
_session.Action();
}
finally
{
_lock.ExitReadLock();
}
}
public static void Method4(string path) {
_lock.EnterWriteLock();
try {
if(_session != null)
_session.Action();
}
finally
{
_lock.ExitWriteLock();
}
}
Great performance, no threading issues!
private static RefCountDisposable _refCountDisposible = new RefCountDisposable();
private static Session _session = new Session();
public Constructor()
{
_refCountDisposible = new RefCountDisposable(
Disposible.Create(() => _session.Disconnect()));
}
public static void Method1() {
using(_refCountDisposible.GetDisposible())
if(_session != null)
_session.Action();
}
public static void Method2() {
using(_refCountDisposible.GetDisposible())
if(_session != null)
_session.Action();
}
public static void Method3() {
using(_refCountDisposible.GetDisposible())
if(_session != null)
_session.Action();
}
public static void Method4(string path) {
_refCountDisposible.Dispose()
}
How about ManualResetEvent?
M4()
{
_event.Reset();
try
//reconnect
finally
_event.Set();
}
M1,2,3()
{
_event.WaitOne();
//do actions
}
Related
I'm not finding the bug, but this thread is stopping after some time of execution, it returns a message "Thread was being aborted."
Sometimes it takes a hour, in another takes four, I can't find a patern, in some cases it never stops, but I can't find anything relate to it
using System.Threading;
namespace NewMVC.infraestructure
{
public class Thread_iFood
{
private static bool inicializado = false;
static Thread_iFood instance = null;
static readonly object padlock = new object();
private const int timer = 30000;
static Timer thProcessaRet = new Timer(PollingIfood, null, Timeout.Infinite, Timeout.Infinite);
private Thread_iFood()
{
}
public static void Reiniciar()
{
inicializado = false;
instance = null;
}
public static Thread_iFood GetInstance
{
get
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Thread_iFood();
}
}
}
return instance;
}
}
internal static async void PollingIfood(Object obj)
{
try
{
thProcessaRet.Change(Timeout.Infinite, Timeout.Infinite);
MetodosAuxiliares.BuscaPedidosIFood();
}
catch (Exception e)
{
LogErros.GravaLog(e, "Thread_iFood/PollingIfood");
//here is where is stopping (Thread was being aborted.)
}
finally
{
thProcessaRet.Change(timer, Timeout.Infinite);
}
}
public void Inicializa()
{
if (!inicializado)
{
inicializado = true;
thProcessaRet.Change(timer, timer);
}
}
}
}
Is using lock(this) instead of lock(lockObject) good implementation in a singleton lazy multi thread implementation?
example:
public class MedicineHelper
{
private static MedicineHelper medicineHelper;
private MedicineHelper()
{
}
public static MedicineHelper GetInstance()
{
if (medicineHelper == null)
{
lock (this)
{
if (medicineHelper == null) medicineHelper = new MedicineHelper();
}
}
return medicineHelper;
}
}
The classical pattern require a lock dedicated object like this:
public class MedicineHelper
{
private static MedicineHelper medicineHelper;
private static Object lockObject = new Object();
private MedicineHelper()
{
}
public static MedicineHelper GetInstance()
{
if (medicineHelper == null)
{
lock (LockObject)
{
if (medicineHelper == null) medicineHelper = new MedicineHelper();
}
}
return medicineHelper;
}
}
It is not a good implementation because you can't do it. "this" is not available from a static method.
This question already has answers here:
Use Unity API from another Thread or call a function in the main Thread
(5 answers)
Closed 6 years ago.
I'm having trouble with a UnityEngine version. (Can't upgrade, game is not mine)
The server RANDOMLY crashes when a specific UnityEngine method is used in a timer/thread (It was fixed in a version, I read It)
It happens totally random, I get a crash log, that starts from the timer/thread and ends at a UnityEngine method. (This never happens when I use It in the main thread)
My question is that Is It possible somehow to call the method from the main thread if the current thread != with the main thread?
Any help is appreciated
This Loom class is able to call the specific method from the Main thread, this is how you do It:
public class Loom : MonoBehaviour
{
public static int maxThreads = 10;
static int numThreads;
private static Loom _current;
private int _count;
public static Loom Current
{
get
{
Initialize();
return _current;
}
}
public void Awake()
{
_current = this;
initialized = true;
}
static bool initialized;
static void Initialize()
{
if (!initialized)
{
if (!Application.isPlaying)
return;
initialized = true;
var g = new GameObject("Loom");
_current = g.AddComponent<Loom>();
}
}
private List<Action> _actions = new List<Action>();
public struct DelayedQueueItem
{
public float time;
public Action action;
}
private List<DelayedQueueItem> _delayed = new List<DelayedQueueItem>();
List<DelayedQueueItem> _currentDelayed = new List<DelayedQueueItem>();
public static void QueueOnMainThread(Action action)
{
QueueOnMainThread(action, 0f);
}
public static void QueueOnMainThread(Action action, float time)
{
if (time != 0)
{
lock (Current._delayed)
{
Current._delayed.Add(new DelayedQueueItem { time = Time.time + time, action = action });
}
}
else
{
lock (Current._actions)
{
Current._actions.Add(action);
}
}
}
public static Thread RunAsync(Action a)
{
Initialize();
while (numThreads >= maxThreads)
{
Thread.Sleep(1);
}
Interlocked.Increment(ref numThreads);
ThreadPool.QueueUserWorkItem(RunAction, a);
return null;
}
private static void RunAction(object action)
{
try
{
((Action)action)();
}
catch
{
}
finally
{
Interlocked.Decrement(ref numThreads);
}
}
public void OnDisable()
{
if (_current == this)
{
_current = null;
}
}
// Use this for initialization
public void Start()
{
}
List<Action> _currentActions = new List<Action>();
// Update is called once per frame
public void Update()
{
lock (_actions)
{
_currentActions.Clear();
_currentActions.AddRange(_actions);
_actions.Clear();
}
foreach (var a in _currentActions)
{
a();
}
lock (_delayed)
{
_currentDelayed.Clear();
_currentDelayed.AddRange(_delayed.Where(d => d.time <= Time.time));
foreach (var item in _currentDelayed)
_delayed.Remove(item);
}
foreach (var delayed in _currentDelayed)
{
delayed.action();
}
}
}
//Usage
public void Call()
{
if (Thread.CurrentThread.ManagedThreadId != TestClass.MainThread.ManagedThreadId)
{
Loom.QueueOnMainThread(() => {
Call();
});
return;
}
Console.WriteLine("Hello");
}
Desription:
I am adding some data to list every second. After every 10 seconds, the data is saved to the database and then I clear the list. If I stop the timer, I am saving the data remaining in the list and then clearing the list and then stopping the timer.
In the above code, Let's say when I stop the timer after 11 seconds, The Class1s list should have only 1 data, but I see there are 11 datas. Can you guys tell what I am doing wrong here? Maybe my use of lock is incorrect or my code is totally incorrect
public class Class1Singleton
{
private static Class1Singleton Class1Singleton;
private static List<Class1> Class1s;
private static Timer saveClass1Timer;
private static readonly object lock1 = new object();
private Class1Singleton()
{
}
public static Class1Singleton getInstance()
{
if (Class1Singleton == null) {
try
{
Class1Singleton = new Class1Singleton();
}
catch (Exception e){}
}
return Class1Singleton;
}
public void StartTimer()
{
if (saveClass1Timer == null)
{
saveClass1Timer = new Timer(10000);
//saveClass1Timer.Interval = 10000;
saveClass1Timer.Elapsed += new ElapsedEventHandler(SaveClass1);
saveClass1Timer.Enabled = true;
}
}
public void SaveClass1(object sender, ElapsedEventArgs e)
{
try {
lock (lock1)
{
new Class1Repository().InsertAllClass1(Class1s);
ClearWorkoutList();
}
}
catch (Exception ex){}
}
public void InsertClass1(List<Class1> Class1)
{
if (Class1s == null)
{
Class1s = new List<Class1>(Class1);
}
else
{
lock (lock1)
{
Class1s.AddRange(Class1);
}
}
}
public void ClearWorkoutList()
{
if (Class1s != null)
{
Class1s.Clear();
}
}
public void StopTimer()
{
if (Class1s != null && Class1s.Count > 0)
{
lock (lock1)
{
new Class1Repository().InsertAllClass1(Class1s);
ClearWorkoutList();
}
}
if (saveClass1Timer != null && saveClass1Timer.Enabled == true)
{
saveClass1Timer.Stop();
}
}
}
I've made a few changes to your code (see comments):
public class Class1Singleton
{
// This is the way Jon Skeet recommends implementing a singleton in C#
// See http://csharpindepth.com/Articles/General/Singleton.aspx
static readonly Class1Singleton instance = new Class1Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Class1Singleton() { }
// There's only one instance of Class1Singleton so there's
// no advantage in making the members static
private List<Class1> Class1s;
private Timer saveClass1Timer;
private readonly object lock1 = new object();
Class1Singleton()
{
}
public static Class1Singleton Instance
{
get { return instance; }
}
public void StartTimer()
{
// If you're using this class in a multi-thread environment,
// all methods that access the list or timer should be locked
lock (lock1)
{
if (saveClass1Timer == null)
{
saveClass1Timer = new Timer(10000);
//saveClass1Timer.Interval = 10000;
saveClass1Timer.Elapsed += new ElapsedEventHandler(SaveClass1);
saveClass1Timer.Enabled = true;
}
}
}
// SaveClass1 doesn't need to be public
private void SaveClass1(object sender, ElapsedEventArgs e)
{
lock (lock1)
{
SaveWorkoutList();
ClearWorkoutList();
}
}
private void SaveWorkoutList()
{
//new Class1Repository().InsertAllClass1(Class1s);
}
public void InsertClass1(List<Class1> Class1)
{
lock (lock1)
{
if (Class1s == null)
Class1s = new List<Class1>(Class1);
else
Class1s.AddRange(Class1);
}
}
private void ClearWorkoutList()
{
if (Class1s != null)
{
Class1s.Clear();
}
}
public void StopTimer()
{
lock (lock1)
{
if (Class1s != null && Class1s.Count > 0)
{
SaveWorkoutList();
ClearWorkoutList();
}
if (saveClass1Timer != null && saveClass1Timer.Enabled == true)
{
saveClass1Timer.Stop();
}
}
}
}
I'm facing a deadlock, my code structure is similar to this:
private delegate void UpdateControlDelegate(string value);
public void UpdateControl(string value)
{
if (txtAddress.InvokeRequired)
{
txtAddress.Invoke(new UpdateControlDelegate(UpdateControl), value);
}
else
{
txtAddress.Text = value; // This is in GroupBox1
txtValue.Text = value; // This is in GroupBox2
}
}
class ThreadHandler
{
List<string> _list = new List<string>();
object _criticalSection = new object();
public ThreadHandler()
{
new Thread(new ThreadStart(Run)).Start();
}
public static ThreadHandler _threadHandler = null;
public static ThreadHandler GetThreadHandler()
{
if (_threadHandler == null)
{
_threadHandler = new ThreadHandler();
}
return _threadHandler;
}
public void Run()
{
while (true)
{
// some code
lock (_criticalSection)
{
foreach (string str in _list)
{
// some Code
}
}
// some code
Thread.Sleep(SomeTime);
}
}
public void AddItem(string item)
{
lock (_criticalSection)
{
_list.Add(item);
}
}
public void RemoveItem(string item)
{
lock (_criticalSection)
{
_list.Remove(item);
}
}
}
But using the same code, I just modified the UpdateControl method like this:
private delegate void UpdateControlDelegate(string value);
public void UpdateControl(string value)
{
if (InvokeRequired)
{
BeginInvoke(new UpdateControlDelegate(UpdateControl), value);
}
else
{
txtAddress.Text = value; // This is in GroupBox1
txtValue.Text = value; // This is in GroupBox2
}
}
This is working fine. What is the problem?
The problem is almost certainly that you're acquiring the lock within a background thread, then calling Control.Invoke, and invoking a delegate (on the UI thread) which tries to acquire the same lock. It can't do that, because the other thread holds the lock - and will keep holding the lock while it waits for the UI operation to complete.
Admittedly there's no locking within the UpdateControl method you've posted, but I suspect that's not the complete code - and you haven't shown where you're using AddItem or RemoveItem.
I note that GetThreadHandler() isn't thread-safe, by the way - that looks like a bug to me...
Are you calling AddItem and RemoveItem from the main thread while calling UpdateControl from the worker thread? That will cause deadlocks.
Here is my code,
public class ValueReader
{
List<IDataReader> _list = new List<IDataReader>();
object _criticalSection = new object();
public ValueReader()
{
//Nothign here
}
public void Attach(IDataReader reader)
{
lock(_criticalSection)
{
_list.Add(reader);
}
}
public void Detach(IDataReader reader)
{
lock(_criticalSection)
{
_list.Remove(reader);
}
}
public void Notify(string value)
{
lock(_criticalSection)
{
foreach(IDataReader reader in _list)
{
reader.Update(value);
}
}
}
public void Start()
{
new Thread(new ThreadStart(Run)).Start();
}
private void Run()
{
while(true)
{
//generate value
Notify(value);
Thread.Sleep(5000);
}
}
}
public interface IDataReader
{
void UpdateControls(string value);
}
public class FirstClass : IDataReader
{
....
......
ValueReader _reader = null;
public FirstClass()
{
_reader = new ValueReader();
_reader.Start();
_reader.Attach(this);
}
private void AddToSmartClient()
{
// _reader has added to SmartClient's WorkItem
}
private delegate void UpdateControlDelegate(string value);
public void UpdateControl(string value)
{
if(txtAddress.InvokeRequired)
{
txtAddress.Invoke(new UpdateControlDelegate(UpdateControl), value);
}
else
{
txtAddress.Text = value;
txtValue.Text = value;
}
}
}
public class SecondClass : IDataReader
{
....
......
ValueReader _reader = null;
public void SecondClass()
{
_reader = ReadFromSmartClient();
_reader.Attach(this);
}
private ValueReader ReadFromSmartClient()
{
reader = //Get from SmartClient's Workitem.
return reader
}
private delegate void UpdateControlDelegate(string value);
public void UpdateControl(string value)
{
if(InvokeRequired)
{
BeginInvoke(new UpdateControlDelegate(UpdateControl), value);
}
else
{
control1.Text = value;
control2.Text = value;
}
}
}
I invokes only FirstClass for some time. In this case its working fine. After some time i invoked the Second class, at this time while calling Attach from secondClass the application is hanging.(i monitered that its comming until Attach methods's lock(_criticalSection).
After some time i converter the Update control in the Frist Class as follow
public void UpdateControl(string value)
{
if(InvokeRequired)
{
BeginInvoke(new UpdateControlDelegate(UpdateControl), value);
}
else
{
txtAddress.Text = value;
txtValue.Text = value;
}
}
This is working well after invoking the SecondClass also. Why its happening?