I am having issue with my singleton class in multi threading environment. This sample program calls method A & B on separate threads. Normally this works ok.
In some cases as shown in the last result at bottom
method A call starts
method B call starts
method B call ends
then method A call ends<---- why is this happening out of order ?
Is this because I am not performing double lock ?
How do I ensure that this does not happen ?
Caller
class Program
{
static void Main(string[] args)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(CallonThread));
Singleton.Instance.Test("B");
Console.ReadKey();
}
static void CallonThread(object a)
{
Singleton.Instance.Test("A");
}
}
Singleton Class
public class Singleton
{
static readonly object Padlock = new object();
private static Singleton _instance;
protected Singleton()
{
}
public static Singleton Instance
{
get
{
lock (Padlock)
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
}
public void Test(string id)
{
if (id == "A")
{
new Data().MethodA();
}
else
{
new Data().MethodB();
}
}
}
Data class
public class Data
{
public void MethodA()
{
Console.WriteLine("Start Method A");
Console.WriteLine("End Method A");
}
public void MethodB()
{
Console.WriteLine("Start Method B");
Console.WriteLine("End Method B");
}
}
Result
This would work to stop MethodA and MethodB from executing simultaneously:
public class Data
{
private static object _padlock = new object();
public void MethodA()
{
lock (_padlock)
{
Console.WriteLine("Start Method A");
Console.WriteLine("End Method A");
}
}
public void MethodB()
{
lock (_padlock)
{
Console.WriteLine("Start Method B");
Console.WriteLine("End Method B");
}
}
}
Related
Example Code (I use Semaphore rather than lock to "lock" that bool member):
public class MsgSendHandler
{
private bool _isSocketSending = false;
private Semaphore _socketSendingSem = new Semaphore(1, 1);
public void Send(INetMsg msg)
{
// Add Msg To MsgQueue
TrySendNext();
}
private void SendCallback(IAsyncResult ar)
{
// Finish Send
_socketSendingSem.WaitOne();
_isSocketSending = false;
_socketSendingSem.Release();
TrySendNext();
}
private bool TrySendNext()
{
_socketSendingSem.WaitOne();
if (_isSocketSending)
return false;
_isSocketSending = true;
_socketSendingSem.Release();
// Socket Begin Send => SendCallback
return true;
}
}
Can I "lock" a value type like this? Is there any better solution?
Expanding on comment:
The way I created mutli-threaded functionality in Unity3D was to have a Dispatcher class that is called once per frame to run any Actions that have been added to a list.
Dispatcher.cs
A simple singleton class that holds the actions with an actual lock when looping through the actions.
public class Dispatcher
{
private static Dispatcher _instance;
public static Dispatcher Instance
{
get
{
if(_instance == null)
{
_instance = new Dispatcher();
}
return _instance;
}
}
private List<Action> _actions = new List<Action> ();
public void AddAction(Action action)
{
lock (_actions)
{
_actions.Add(action);
}
}
public void CompleteActions()
{
lock (_actions)
{
foreach (Action action in _actions)
{
action();
}
}
_actions.Clear();
}
public void ClearActions()
{
lock (_actions)
{
_actions.Clear();
}
}
}
DispatcherUpdate.cs
Another simple class that's added to a GameObject within the scene to call the Dispatcher to Complete the aquired Actions.
public class DispatcherUpdate : MonoBehaviour
{
private void Awake()
{
Dispatcher.Instance.ClearActions();
}
private void Update()
{
Dispatcher.Instance.CompleteActions();
}
}
Usage
Dispatcher.Instance.AddAction(() => TrySendNext());
This is the method I've used for Async multi-threading with SignalR
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");
}
I'm writing a program in C#, which must be executed as a service.
In my main class, I have object1 of class1 and a Thread t, and I instantiate object1 and use the thread t to run the method "run" of this object on the onStart method of this main class (object1 is a class variable). In the method onStop, I call the stop() method of object1.
In class1 I have a list, and in the method run() of class1 I add an element to the list (I've checked it gets added). In the method stop() I try to retrieve this element, but the list has no elements.
partial class ServiceClass: ServiceBase
{
volatile Class1 object1 = new Class1();
volatile Thread t = null;
public ServiceClass()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
t = new Thread(object1.run);
t.Start();
}
catch (Exception e)
{
t.Join();
}
}
protected override void OnStop()
{
object1.Stop();
t.Join();
}
}
class Class1
{
private List<FileProcessor> fileProcessors = new List<FileProcessor>();
private FileSystemWatcher awatcher = null;
public Class1()
{
}
public void run()
{
FileProcessor fp = new FileProcessor();
fileProcessors.Add(fp);
awatcher = new FileSystemWatcher("C:\\Example", "*.csv");
awatcher.IncludeSubdirectories = false;
awatcher.Created += new FileSystemEventHandler(awatcher_Created);
awatcher.Renamed += new RenamedEventHandler(awatcher_Renamed);
awatcher.InternalBufferSize = 4096 * 500;
awatcher.EnableRaisingEvents = true;
}
public void Stop()
{
foreach (FileProcessor fileProcessor in this.fileProcessors)
{
if (fileProcessor != null)
{
fileProcessor.Stop();
}
}
if (awatcher != null)
{
awatcher.EnableRaisingEvents = false;
awatcher.Dispose();
}
Environment.Exit(-2);
}
void awatcher_Renamed(object sender, RenamedEventArgs e)
{
if (e.OldName.Replace(".prepare", "").Equals(e.Name) && e.Name.EndsWith(".csv") && !e.Name.Contains(ConfigurationManager.AppSettings["TestParameter"]))
{
FileInfo fi = new FileInfo(e.FullPath);
awatcher_Created(sender, new FileSystemEventArgs(WatcherChangeTypes.Created, fi.DirectoryName, e.Name));
}
}
void awatcher_Created(object sender, FileSystemEventArgs e)
{
// Nothing yet
}
}
When the Stop() function gets called, awatcher is null and the list is empty, as if it run hadn't been called. Why does this reference get lost?
Edit: If I declare those variables as static, it works right. However, I'd prefer to use non-static variables.
Okay, so I have tried to recreate your scenario. Here it is as a Fiddle. Unfortunately, I was unable to reproduce the missing list item.
using System;
using System.Threading;
using System.Collections.Generic;
public class MyMainClass
{
public static Class1 object1 = new Class1();
public static void Main()
{
Console.WriteLine("Mimic a service's OnStart and OnStop");
OnStart();
Console.WriteLine("Press any key to stop");
Console.ReadLine();
OnStop();
}
public static void OnStart()
{
Console.WriteLine("Started");
Thread t = new Thread(new ThreadStart(object1.Run));
t.Start();
}
public static void OnStop()
{
object1.Stop();
Console.WriteLine("Stopped");
}
}
public class Class1
{
public List<object> list = new List<object>();
public void Run()
{
list.Add("Some Element");
}
public void Stop()
{
Console.WriteLine(list[0]);
}
}
I was experimenting with the new C# await feature. I made a custom awaiter implementation as follows:
using System;
using System.Runtime.CompilerServices;
using System.Threading;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
T1();
Console.WriteLine("After t1");
}
private static async void T1()
{
CustomAwaitable a = new Sleeper().Sleep();
object r = await a;
Console.WriteLine("sleeper awakes " + r);
}
}
internal class CustomAwaitable
{
private readonly Sleeper m_sleeper;
public CustomAwaitable(Sleeper s)
{
m_sleeper = s;
}
public MyAwaiter GetAwaiter()
{
return new MyAwaiter(m_sleeper);
}
}
internal class Sleeper
{
public ManualResetEvent Handle = new ManualResetEvent(false);
public bool Awake { get; set; }
public int Result
{
get { return Environment.TickCount; }
}
public CustomAwaitable Sleep()
{
new Thread(() =>
{
Thread.Sleep(5000);
Awake = true;
Handle.Set();
}).Start();
Console.WriteLine("begin sleeping " + Result);
return new CustomAwaitable(this);
}
}
internal class MyAwaiter : INotifyCompletion
{
private readonly Sleeper m_sleeper;
public MyAwaiter(Sleeper sleeper)
{
m_sleeper = sleeper;
}
public bool IsCompleted
{
get { return m_sleeper.Awake; }
}
public void OnCompleted(Action continuation)
{
// This works!!
//new Thread(() =>
//{
// m_sleeper.Handle.WaitOne();
// continuation();
//}).Start();
// This doesn't work!!
Action k = () =>
{
m_sleeper.Handle.WaitOne();
continuation();
};
k.BeginInvoke(null, null);
}
public object GetResult()
{
return m_sleeper.Result;
}
}
}
The problem is that, in the OnCompleted method, when I schedule the continuation code execution using BeginInvoke, the GetResult method is never called. But when I create a thread manually to do the same thing, everything works as expected. I know that BeginInvoke uses the thread pool internally, which should work the same way as the thread approach (I know that there is a thread count limit with thread pool, but it is negligible in this case as I am not running anything else).
What are your ideas? Thanks!
I have a console application that essentially looks like this
class Program
{
static void Main(string[] args)
{
DoStuffService svc = new DoStuffService();
svc.Start();
}
}
class DoStuffService
{
public void Start()
{
Task.Factory.StartNew(() => { LongRunningOperation() });
}
private void LongRunningOperation()
{
// stuff
}
}
What's the best way these days to ensure my console application doesn't exit before LongRunningOperation() is complete, and also allows me a way to be notified in the console application (for logging purposes for instance) that LongRunningOperation() is complete.
call Wait() on the task. For example:
class Program
{
static void Main(string[] args)
{
DoStuffService svc = new DoStuffService();
svc.Start();
// stuff...
svc.DelayTilDone();
}
}
public class DoStuffService
{
Task _t;
public void Start()
{
_t = Task.Factory.StartNew(() => { LongRunningOperation(); });
}
public void DelayTilDone()
{
if (_t==null) return;
_t.Wait();
}
private void LongRunningOperation()
{
System.Threading.Thread.Sleep(6000);
System.Console.WriteLine("LRO done");
}
}
In addition to Cheeso's answer, you'll want to handle Console.CancelKeyPress so that you can display a busy message and set e.Cancel = True.
There's nothing you can do to prevent them from killing the process, but you can at least handle Ctrl+C and Ctrl+Break.
There is a similar thread C# multi-threaded console application - Console quits before threads complete
You can simply return a started task and Wait() or ContinueWith() on it:
using System.Diagnostics;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
DoStuffService svc = new DoStuffService();
svc.Start().Wait();//bool res = svc.Start()
Trace.WriteLine("333333333333333");
}
}
public class DoStuffService
{
public Task Start()
{
return Task.Factory.StartNew
(() =>
{
Trace.WriteLine("111111111");
LongRunningOperation(); ;
});
}
private void LongRunningOperation()
{
System.Threading.Thread.Sleep(3000);
Trace.WriteLine("2222222222");
}
}
A task will block the parent thread until completion, if to access its Result property, so:
using System.Diagnostics;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
DoStuffService svc = new DoStuffService();
svc.Start();//bool res = svc.Start()
Trace.WriteLine("333333333333333");
}
}
public class DoStuffService
{
public Task<bool> MyTask;
public bool Start()
{
MyTask = Task.Factory.StartNew<bool>
(() =>
{
Trace.WriteLine("111111111");
return LongRunningOperation();;
});
return MyTask.Result;
}
private bool LongRunningOperation()
{
System.Threading.Thread.Sleep(3000);
Trace.WriteLine("2222222222");
return true;
}
}