仅执行一次代码块

时间:2012-10-26 14:04:09

标签: c# wpf multithreading

以下代码块预先在C#中加载对象。

public bool IsModelLoaded { get; set; }
public override MyObject Load()
    {
        if (!IsModelLoaded)
        {
            Model = MyService.LoadMyObject(Model);
            IsModelLoaded = true;
        }
        return Model;
    }

我的目的是只运行一次这个块,因此只加载一次Model。 不过,这个代码块从2个不同的线程运行两次..

如何确保此块只运行一次? (在多线程上)。

谢谢。

7 个答案:

答案 0 :(得分:3)

最简单的是添加

[MethodImpl(MethodImplOptions.Synchronized)]
public override MyObject Load()
{
   //snip
}

但请注意,这会锁定整个对象,而不仅仅是方法。不是很好的练习。

http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.methodimploptions.aspx

同步

指定该方法一次只能由一个线程执行。静态方法锁定类型,而实例方法锁定实例。只有一个线程可以在任何实例函数中执行,并且只有一个线程可以在任何类的静态函数中执行。

答案 1 :(得分:2)

使用Lazy<T> Class

private readonly Lazy<MyObject> myObject;

public MyClass()
{
    myObject = new Lazy<MyObject>(() =>
    {
        return MyService.LoadMyObject();
    }, LazyThreadSafetyMode.ExecutionAndPublication);
}

public bool IsModelLoaded
{
    get { return myObject.IsValueCreated; }
}

public override MyObject Load()
{
    return myObject.Value;
}

答案 2 :(得分:1)

我正在尝试实施singleton模式。但是你的版本不是线程安全的。在此处阅读更多内容:http://www.dofactory.com/Patterns/PatternSingleton.aspx。尝试使用此实现:

public sealed class Singleton
{
    static Singleton instance=null;
    static readonly object padlock = new object();

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance==null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}

答案 3 :(得分:1)

Action myCodeBlock = ()=>
{
  //do your job
  //...
  myCodeBlock = ()=>{};
}

一旦调用myCodeBlock(),它将被不执行任何操作的方法重写。您仍然需要确保安全地调用此metod - 使用lock或其他任何内容。

答案 4 :(得分:1)

答案 5 :(得分:1)

如果你想编写线程安全代码并确保该块只运行一次,你可以像这样写:

private System.Object lockThis = new System.Object(); 
public override MyObject Load()
{
    lock (lockThis) {
        if (!IsModelLoaded)
        {
            Model = MyService.LoadMyObject(Model);
            IsModelLoaded = true;
        }
    }
    return Model;
}

答案 6 :(得分:0)

创建一个静态对象(如布尔值),通过将代码置于if语句中来确定代码是否已运行:)

编辑:我不确定这是否是线程安全的,所以它可能不适合你。