3

古いフォーマットから新しいフォーマットへの「移行」を行う機能があります。これはオブジェクトのコンストラクターで発生する必要がありますが、引数が必要なため静的コンストラクターでは発生しません。コードを1回だけ実行するにはどうすればよいですか?

いくつかのコンテキストの場合:

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

シングルトンパターンが機能するはずです。

パロットジョンスキート: 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 に答える
0

あなたはについて読むべきですmonitorssemaphorsそしてsigelton design-pattern

C#のMutexとセマフォとは何ですか?どこに実装する必要がありますか?

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://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;
        }
    }
} 
于 2013-02-21T17:24:38.780 に答える