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();
}
}
}
}
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);
}
}
}
}
How can I properly unsubscribe to an event and be sure that the called method is not called now ?
My problem is with this kind of code :
public class MyClassWithEvent
{
public event EventHandler MyEvent;
public int Field;
}
public class MyMainClass
{
private MyClassWithEvent myClass;
public void Start()
{
myClass.MyEvent += new EventHandler(doSomething);
}
public void Stop()
{
myClass.MyEvent -= new EventHandler(doSomething);
myClass = null;
}
private void doSomething()
{
myClass.Field = 42;
}
}
If myClass = null is called while doSomething is executing, instruction myClass.Field = 42 raise an error because myClass is null.
How can I be sure that doSomething is not executing before setting myClass = null ?
Edit:
Other example:
public void Stop()
{
myClass.MyEvent -= new EventHandler(doSomething);
// Can I add a function here to be sure that doSomething is not running ?
myClass.Field = 101;
}
In that case, I will not be sure if myClass.Field is 42 or 101.
Edit2:
Apparently my question is not as simple as I thought. I will explain my precise case.
My code is :
public class MyMainClass
{
object camera;//can be type uEye.Camera or DirectShowCamera
bool isRunning = false;
public void Start()
{
if (camera is uEye.Camera)
{
camera.EventFrame += new EventHandler(NewFrameArrived);
}
else if (camera is DirectShowCamera)
{
//other init
}
isRunning = true;
}
public void Stop()
{
if (camera is uEye.Camera)
{
camera.EventFrame -= new EventHandler(NewFrameArrived);
camera.exit;
}
else if (camera is DirectShowCamera)
{
//other stop
}
isRunning = false;
}
public void ChangeCamera(object new camera)
{
if (isRunning)
Stop()
camera = new camera();
}
void NewFrameArrived(object sender, EventArgs e)
{
uEye.Camera Camera = sender as uEye.Camera;
Int32 s32MemID;
Camera.Memory.GetActive(out s32MemID);
lock (_frameCameralocker)
{
if (_frameCamera != null)
_frameCamera.Dispose();
_frameCamera = null;
Camera.Memory.ToBitmap(s32MemID, out _frameCamera);
}
Dispatcher.Invoke(new Action(() =>
{
lock (_frameCameralocker)
{
var bitmapData = _frameCamera.LockBits(
new System.Drawing.Rectangle(0, 0, _frameCamera.Width, _frameCamera.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, _frameCamera.PixelFormat);
if (_frameCamera.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
{
DeviceSource = System.Windows.Media.Imaging.BitmapSource.Create(
bitmapData.Width, bitmapData.Height, 96, 96, System.Windows.Media.PixelFormats.Gray8, null,
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
}
_frameCamera.UnlockBits(bitmapData);
if (OnNewBitmapReady != null)
OnNewBitmapReady(this, null);
}
}));
}
}
And when I change the camera from uEye to directshow sometime I have a AccessViolationException in DeviceSource = System.Windows.Media.Imaging.BitmapSource.Create (method NewFrameArrived) because I try to create BitmapSource from an exited camera
From your updated question, the only thing you need to do is just lock the Stop() action from the same lock as the Dispatcher.Invoke
public void Stop()
{
lock(_frameCameralocker)
{
if (camera is uEye.Camera)
{
camera.EventFrame -= new EventHandler(NewFrameArrived);
camera.exit;
}
else if (camera is DirectShowCamera)
{
//other stop
}
isRunning = false;
}
}
This will make sure all NewFrameArrived calls finished or have not started before you create the new camera. Then inside the dispatcher check to see if you are running or not just in case a frame was queued before a Stop() call was started and completed.
Dispatcher.Invoke(new Action(() =>
{
lock (_frameCameralocker)
{
if(!isRunning)
return;
var bitmapData = _frameCamera.LockBits(
new System.Drawing.Rectangle(0, 0, _frameCamera.Width, _frameCamera.Height),
System.Drawing.Imaging.ImageLockMode.ReadOnly, _frameCamera.PixelFormat);
if (_frameCamera.PixelFormat == System.Drawing.Imaging.PixelFormat.Format8bppIndexed)
{
DeviceSource = System.Windows.Media.Imaging.BitmapSource.Create(
bitmapData.Width, bitmapData.Height, 96, 96, System.Windows.Media.PixelFormats.Gray8, null,
bitmapData.Scan0, bitmapData.Stride * bitmapData.Height, bitmapData.Stride);
}
_frameCamera.UnlockBits(bitmapData);
if (OnNewBitmapReady != null)
OnNewBitmapReady(this, null);
}
}));
Maybe a good use for Monitor ?
The idea is that you use a lock to make sure you are not using the same resource twice at the (almost) same time :
public class MyClassWithEvent
{
public event EventHandler MyEvent;
public int Field;
}
public class MyMainClass
{
private MyClassWithEvent myClass;
private object mylock;
public void Start()
{
myClass.MyEvent += new EventHandler(doSomething);
}
public void Stop()
{
myClass.MyEvent -= new EventHandler(doSomething);
Monitor.Enter(mylock); //If somebody else already took the lock, we will wait here
myClass = null;
Monitor.Exit(mylock); //We release the lock, so others can access it
}
private void doSomething()
{
Monitor.Enter(mylock);
if myClass != null
{
myClass.Field = 42;
}
Monitor.Exit(mylock);
}
}
EDIT
According to comments, Lock would be a better use (actually a short-hand for Monitor) :
public class MyClassWithEvent
{
public event EventHandler MyEvent;
public int Field;
}
public class MyMainClass
{
private MyClassWithEvent myClass;
private object mylock;
public void Start()
{
myClass.MyEvent += new EventHandler(doSomething);
}
public void Stop()
{
myClass.MyEvent -= new EventHandler(doSomething);
lock (mylock) //If somebody else already took the lock, we will wait here
{
myClass = null;
} //We release the lock, so others can access it
}
private void doSomething()
{
lock(mylock)
{
if myClass != null
{
myClass.Field = 42;
}
}
}
}
Instead
myClass.Field = 42;
Do
val local = myClass;
if (local != null)
local.Field = 42;
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");
}
copy paste the following code in new C# console app.
class Program
{
static void Main(string[] args)
{
var enumerator = new QueuedEnumerator<long>();
var listenerWaitHandle = Listener(enumerator);
Publisher(enumerator);
listenerWaitHandle.WaitOne();
}
private static AutoResetEvent Listener(IEnumerator<long> items)
{
var #event = new AutoResetEvent(false);
ThreadPool.QueueUserWorkItem((o) =>
{
while (items.MoveNext())
{
Console.WriteLine("Received : " + items.Current);
Thread.Sleep(2 * 1000);
}
(o as AutoResetEvent).Set();
}, #event);
return #event;
}
private static void Publisher(QueuedEnumerator<long> enumerator)
{
for (int i = 0; i < 10; i++)
{
enumerator.Set(i);
Console.WriteLine("Sended : " + i);
Thread.Sleep(1 * 1000);
}
enumerator.Finish();
}
class QueuedEnumerator<T> : IEnumerator<T>
{
private Queue _internal = Queue.Synchronized(new Queue());
private T _current;
private bool _finished;
private AutoResetEvent _setted = new AutoResetEvent(false);
public void Finish()
{
_finished = true;
_setted.Set();
}
public void Set(T item)
{
if (_internal.Count > 3)
{
Console.WriteLine("I'm full, give the listener some slack !");
Thread.Sleep(3 * 1000);
Set(item);
}
else
{
_internal.Enqueue(item);
_setted.Set();
}
}
public T Current
{
get { return _current; }
}
public void Dispose()
{
}
object System.Collections.IEnumerator.Current
{
get { return _current; }
}
public bool MoveNext()
{
if (_finished && _internal.Count == 0)
return false;
else if (_internal.Count > 0)
{
_current = (T)_internal.Dequeue();
return true;
}
else
{
_setted.WaitOne();
return MoveNext();
}
}
public void Reset()
{
}
}
}
2 threads (A,B)
A thread can provide one instance at a time and calls the Set method
B thread wants to receive a sequence of instances (provided by thread A)
So literally transforming an Add(item), Add(item), .. to a IEnumerable between different threads
Other solutions also welcome of course!
Sure - this code might not be the best way to do it, but here was my initial stab at it:
Subject<Item> toAddObservable;
ListObservable<Item> buffer;
void Init()
{
// Subjects are an IObservable we can trigger by-hand, they're the
// mutable variables of Rx
toAddObservable = new Subject(Scheduler.TaskPool);
// ListObservable will hold all our items until someone asks for them
// It will yield exactly *one* item, but only when toAddObservable
// is completed.
buffer = new ListObservable<Item>(toAddObservable);
}
void Add(Item to_add)
{
lock (this) {
// Subjects themselves are thread-safe, but we still need the lock
// to protect against the reset in FetchResults
ToAddOnAnotherThread.OnNext(to_add);
}
}
IEnumerable<Item> FetchResults()
{
IEnumerable<Item> ret = null;
buffer.Subscribe(x => ret = x);
lock (this) {
toAddObservable.OnCompleted();
Init(); // Recreate everything
}
return ret;
}
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?