3

我有一个功能可以从旧格式“迁移”到新格式。我需要在我的对象的构造函数中发生这种情况,但不是静态构造函数,因为需要一个参数。我怎样才能让一段代码只执行一次?

对于某些情况:

class Foo
{
  public Foo(string bar)
  {
    ShouldOnlyExecuteOnce(bar);
  }
}

然后用法可能是(每行一个不同的线程)

var f = new Foo("bar");
var fb = new Foo("meh");
etc

我怎样才能正确地保护 " ShouldOnlyExecuteOnce" 方法?

因为这是一种“迁移”类型的函数,所以我希望创建的第一个对象“获胜”并将旧数据迁移到这个新对象中。稍后构造的对象不应尝试执行此函数,即使它们的参数不同

4

7 回答 7

1

您可以使用双重检查锁定。

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;
                }
            }
        }
    }
}
于 2013-02-21T17:23:00.070 回答
1

我通常会建议不要实现诸如双重检查锁定之类的微妙机制,尤其是当您已经在 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);
于 2017-07-25T14:00:14.097 回答
0

你应该阅读关于monitors,semaphorssigelton design-pattern

c#中的互斥量和信号量是什么?我们需要在哪里实施?

http://www.c-sharpcorner.com/UploadFile/1d42da/threading-with-semaphore-in-C-Sharp/

于 2013-02-21T17:19:19.193 回答
0

我不知道,但我猜/尝试:

1 - 充当包装器并在静态构造函数中调用您的方法的静态类

2 - 一些 IoC 容器?

3 - 单身人士?

4 - 锁定?

5 - 以上所有?

于 2013-02-21T17:24:32.500 回答
0

我同意 P.Brian 的观点,这似乎是一种单例模式。你可以在这里看到一篇非常好的文章http://cshapindepth.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;
        }
    }
} 
于 2013-02-21T17:24:38.780 回答
0

单例模式应该可以工作。

鹦鹉乔恩·斯基特: 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;
         }
     }
 } 

单例是一次性构建的。虽然,关于传入新字符串值的部分可能会出现问题。是否在所有连续调用中都忽略此值?

于 2013-02-21T17:17:07.600 回答
0

你需要一个互斥锁。这正是为这种用例互斥锁而设计的。

http://www.dotnetperls.com/mutex

于 2013-02-21T17:17:34.030 回答