8

以下代码块在 C# 中执行对象的加载。

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

我的意图是只运行这个块一次,因此Model只加载一次。然而,这个代码块从 2 个不同的线程运行了两次。

我怎样才能确保这个块只运行一次?(在多个线程上)。

4

7 回答 7

4

使用Lazy<T> 类

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;
}
于 2012-10-26T14:06:37.483 回答
2

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

private System.Object lockThis = new System.Object(); 
public override MyObject Load()
{
    lock (lockThis) {
        if (!IsModelLoaded)
        {
            Model = MyService.LoadMyObject(Model);
            IsModelLoaded = true;
        }
    }
    return Model;
}
于 2012-10-26T14:08:59.827 回答
2

最简单的方法是添加

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

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

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

同步的

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

于 2012-10-26T14:06:36.253 回答
2

我正在尝试实现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;
            }
        }
    }
}
于 2012-10-26T14:06:46.190 回答
1
Action myCodeBlock = ()=>
{
  //do your job
  //...
  myCodeBlock = ()=>{};
}

调用myCodeBlock()一次后,它将被什么都不做的方法重写。您仍然需要确保安全地调用此方法 - 使用lock或其他。

于 2012-10-26T14:07:12.943 回答
1

您可以使用lock 语句(C# 参考)

于 2012-10-26T14:07:14.397 回答
-1

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

编辑:我不确定这是否是线程安全的,所以它可能不是你的解决方案。

于 2012-10-26T14:06:08.367 回答