访问被处置对象

时间:2009-11-09 12:16:44

标签: .net locking

我正在使用以下类来提供对asp.net应用程序中语言资源的访问。我通过从数据库中获取文本值来呈现所选语言的页面。所以我尝试通过在静态数据表中缓存来优化获取文本。但是,我不确定从tableResources读取它是否总是安全的,它可以由UpdateResources函数重新创建。我知道GC在Rows.Find读取时不会释放该对象,但我对GC知之甚少。无论如何,它可能会导致死锁或卡住GC。 (我认为IL指令不是原子的,除非那些编译成单个CPU指令的指令)。 请帮助我理解这一点。

public class Resources
{
    public static DataTable tableResources;
    public static object objSync = new object();
    private PageLangs PageLang;

    static Resources()
    {
        UpdateResources();
    }

    public Resources(PageLangs pageLang)
    {
        PageLang = pageLang;
    }

    public static void UpdateResources()
    {
        OleDbConnection con = ProjectLib.CreateDBConnection();
        try
        {
            con.Open();

            OleDbDataAdapter adap = new OleDbDataAdapter("SELECT Resource0,Resource1,Resource2,Resource3,Resource4,Resource5,Resource6,ResourceCode FROM Resources", con);
            DataTable dt = new DataTable();
            adap.Fill(dt);
            adap.Dispose();
            dt.PrimaryKey = new DataColumn[] { dt.Columns["ResourceCode"] };
            // DataTable is thread-safe for multiple reads but not for writes so sync. it.
            lock (objSync)
            {
                tableResources = dt;
            }
        }
        catch
        {
        }
        finally
        {
            ProjectLib.CloseDBConnection(con);
        }
    }

    public string this[string resourceCode]
    {
        get
        {
            try
            {
                DataRow row = tableResources.Rows.Find(resourceCode);

                if (row != null)
                    return row[(int)PageLang] as string;
                else
                    return resourceCode;
            }
            catch
            {
                return null;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我使用了以下类而不是DataTable。在设置了对象的新实例后,我通过

强制进行垃圾回收
GC.Collect(); 
GC.WaitForPendingFinalizers();

如果调用AMethod(),则不会调用DataTableX的析构函数,但如果不调用它,则调用析构函数。

我即使在即将调用objDataTableX.AMethod()时也进行了测试。当单个指令获取objDataTableX引用时,我已进入反汇编代码并冻结调试器,然后继续使用另一个更改引用的线程进行调试。引用已更改,但之前的DataTableX引用未被处理,因此我解冻了另一个线程,并且它与之前的引用一起执行良好。

public class DataTableX
{
    public void AMethod()
    {
    }

    ~DataTableX()
    {

    }
}

答案 1 :(得分:0)

我认为您希望实现index属性的调用者不会受到来自另一个线程的UpdateResources函数的并行调用的干扰。

您的单一锁定声明完全没有效果。 当您想要同步tableResources成员的访问权限时 - 您必须同步所有访问它的地方(UpdateResources和index属性)。

当你不同步时,可能会有一个提升条件,因为当你调用UpdateResources时,没有对旧DataSet的引用 - 即使当时正在执行tableResources.Rows.Find(resourceCode)。

此外,您应该将tableResources的访问修饰符修改为private或protected。

关于性能,您可能希望实现更复杂的同步机制,该机制更适合多读者单一作者模式。请参阅以下链接:

  1. 另一个SO Question
  2. Wikipedia article
相关问题