I needed something similar – I had a method that should only be called once (initialize) and I wanted to implement something similar to the call_once I’ve been using for my C++ development.
- Exactly one execution of exactly one of the functions (passed as
fto the invocations in the group) is performed. It is undefined which function will be selected for execution. The selected function runs in the same thread as
thecall_onceinvocation it was passed to.
- No invocation in the group returns before the abovementioned execution of the selected function is completed successfully, that is, doesn't exit via an exception.
- If the selected function exits via exception, it is propagated to the caller. Another function is then selected and executed.
public static class Call
{
public static void Once(OnceFlag flag, Action action)
{
if (flag.CheckIfNotCalledAndSet)
{
action.Invoke();
}
}
}
public class OnceFlag
{
private const int NotCalled = 0;
private const int Called = 1;
private int _state = NotCalled;
internal bool CheckIfCalledAndSet
{
get
{
var prev = Interlocked.Exchange(ref _state, Called);
return prev == NotCalled;
}
}
internal void Reset()
{
Interlocked.Exchange(ref _state, NotCalled);
}
}
class Program
{
static OnceFlag _flag = new OnceFlag();
static void Main(string[] args)
{
var t1 = new Thread(() => DoOnce(1));
var t2 = new Thread(() => DoOnce(2));
var t3 = new Thread(() => DoOnce(3));
var t4 = new Thread(() => DoOnce(4));
t1.Start();
t2.Start();
t3.Start();
t4.Start();
t1.Join();
t2.Join();
t3.Join();
t4.Join();
}
private static void DoOnce(int index)
{
Call.Once(_flag, () => Console.WriteLine("Callled (" + index + ")"));
}
}
public static void Once(OnceFlagSimple flag, Action action)
{
lock (flag)
{
if (flag.CheckIfNotCalled)
{
action.Invoke();
flag.Set();
}
}
}
Labels: .NET, async, C#, Multi-threading