我有一个从旧格式“迁移”到新格式的功能。我需要在我的对象的构造函数中发生这种情况,而不是静态构造函数,因为需要参数。如何让一段代码只执行一次?
对于某些情况:
class Foo
{
public Foo(string bar)
{
ShouldOnlyExecuteOnce(bar);
}
}
然后使用可能是(每行都有一个不同的线程)
var f = new Foo("bar");
var fb = new Foo("meh");
etc
如何正确保护“ShouldOnlyExecuteOnce
”方法?
因为这是一种“迁移”类型的函数,我希望创建的第一个对象“win”并将旧数据迁移到这个新对象中。后来构造的对象不应该尝试执行此函数,即使它们的参数不同
答案 0 :(得分:3)
您可以使用双重检查锁定。
class Foo
{
private static bool ShouldOnlyExecuteOnceExecuted = false;
private static readonly object Locker = new object();
public Foo(string bar)
{
SetShouldOnlyExecuteOnce(bar);
}
private void SetShouldOnlyExecuteOnce(string bar)
{
if(!ShouldOnlyExecuteOnceExecuted)
{
lock(Locker)
{
if(!ShouldOnlyExecuteOnceExecuted)
{
ShouldOnlyExecuteOnce(bar);
ShouldOnlyExecuteOnceExecuted = true;
}
}
}
}
}
答案 1 :(得分:0)
Singleton模式应该有效。
Parrotting Jon Skeet:http://csharpindepth.com/articles/general/singleton.aspx
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
Singleton's构造一次。虽然,关于传递新字符串值的部分可能会出现问题。是否在所有连续呼叫中忽略此值?
答案 2 :(得分:0)
你需要一个互斥锁。这正是用于设计互斥锁的用例。
答案 3 :(得分:0)
您应该阅读monitors
,semaphors
和sigelton design-pattern
What is the Mutex and semaphore In c#? where we need to implement?
http://www.c-sharpcorner.com/UploadFile/1d42da/threading-with-semaphore-in-C-Sharp/
答案 4 :(得分:0)
我不知道,但我猜/尝试:
1 - 作为包装器的静态类,在静态构造函数中调用您的方法
2 - 一些IoC容器?
3 - 单身人士?
4 - 锁?
5 - 以上全部?
答案 5 :(得分:0)
我同意P.Brian的看法,这似乎是一个单身人士模式。你可以在这里看到一篇非常好的文章http://csharpindepth.com/articles/general/singleton.aspx,它可以很好地分解它。通常,最好的解决方案是#4;
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
private Singleton()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
答案 6 :(得分:0)
我一般建议不要实现微重机制,例如双重检查锁定,特别是当你已经在BCL中实现它们时。在这种情况下:
public class SafeInitializater
{
private bool _initialized;
private object _dummy;
private object _syncLock;
public void InitializeOnce(Action initializer)
{
LazyInitializer.EnsureInitialized(ref _dummy, ref _initialized, ref _syncLock,
() => {
initializer();
return null;
});
}
}
使用示例:
var initializer = new SafeInitializater(); //or you could make this static somewhere
var t1 = Task.Run(() =>
{
Console.WriteLine($"Task {Task.CurrentId} entering the race");
initializer.InitializeOnce(() => Console.WriteLine($"Task {Task.CurrentId} won!"));
});
var t2 = Task.Run(() =>
{
Console.WriteLine($"Task {Task.CurrentId} entering the race");
initializer.InitializeOnce(() => Console.WriteLine($"Task {Task.CurrentId} won!"));
});
await Task.WhenAll(t1, t2);