【问题标题】:ASP.net static DataView usage accross entire visitors - public static function - is this way thread safe?跨整个访问者的 ASP.net 静态 DataView 使用 - 公共静态函数 - 这种方式线程安全吗?
【发布时间】:2012-11-29 11:49:28
【问题描述】:

好的,简单的问题。在下面的类中做 returnAttackDescription 函数线程安全。

我的意思是假设同时使用所有不同的参数对该函数进行 100 次不同的调用(因为它需要 3 个参数)

这个工作线程安全吗?如果不是,我怎样才能使它线程安全?这个数据视图会在第一次函数调用时被初始化吗?还是什么时候?

谢谢

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;

public static class Descriptions
{
    private static DataView dvAttacks;

    static Descriptions()
    {
        try
        {
            DataSet dsTempEnemyAttack = DbConnection.db_Select_Query("select AttackType,AttackCategory,BasePower,Accuracy,MoreFacts_tr,MoreFacts_en,Priority from tblAttacks");
            dvAttacks = new DataView(dsTempEnemyAttack.Tables[0]);
        }
        catch
        {

        }
    }

    public static string returnAttackDescription(string srAttackName, string srLang, string srCssClassName)
    {
        dvAttacks.RowFilter = "AttackName='" + srAttackName + "'";

        string srReturn = string.Format("<div class=\"{0}\" title=\"" +
                "{0}<hr/>" +
                "Type: {1}<br/>" +
                "Category: {2}<br/>" +
                "Base Power: {3}<br/>" +
                "Accuracy: {4}<br/>" +
                "Priority: {5}<br/>" +
                "Effect: {6}\"></div>", srCssClassName, srAttackName,
                dvAttacks[0]["AttackType"].ToString(),
                dvAttacks[0]["AttackCategory"].ToString(),
                dvAttacks[0]["BasePower"].ToString(),
                dvAttacks[0]["Accuracy"].ToString(),
                dvAttacks[0]["Priority"].ToString(), 
                dvAttacks[0]["MoreFacts_" + srLang].ToString());

        return srReturn;
    }
}

第二种可能的解决方案是这个线程安全吗?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;

public static class Descriptions
{
    private static DataView dvAttacks;

    static Descriptions()
    {
        try
        {
            dsAttacks = DbConnection.db_Select_Query("select AttackName,AttackType,AttackCategory,BasePower,Accuracy,MoreFacts_tr,MoreFacts_en,Priority from tblAttacks");
        }
        catch
        {

        }
    }

    public static string returnAttackDescription2(string srAttackName, string srLang, string srCssClassName)
    {
        var results = (from r in dsAttacks.Tables[0].AsEnumerable()
                       where r.Field<string>("AttackName") == srAttackName
                       select new
                           {

                               srAttackType = r.Field<string>("AttackType"),
                               srAttackCategory = r.Field<string>("AttackCategory"),
                               irBasePower = r.Field<Int16>("BasePower"),
                               irAccuracy = r.Field<Int16>("Accuracy"),
                               irPriority = r.Field<Int16>("Priority"),
                               srMoreFacts = r.Field<string>("MoreFacts_" + srLang)
                           }
                        ).FirstOrDefault();

        string srReturn = string.Format("<div class=\"{0}\" title=\"" +
        "{0}<hr/>" +
        "Type: {1}<br/>" +
        "Category: {2}<br/>" +
        "Base Power: {3}<br/>" +
        "Accuracy: {4}<br/>" +
        "Priority: {5}<br/>" +
        "Effect: {6}\"></div>", srCssClassName, srAttackName,
        results.srAttackType,
        results.srAttackCategory,
        results.irBasePower,
        results.irAccuracy,
        results.irPriority, results.srMoreFacts);

        return srReturn;
    }
}

c#asp.net 4.0

【问题讨论】:

  • 添加了第二种可能的解决方案

标签: c# asp.net function static thread-safety


【解决方案1】:

解决方案不是真正的线程安全,我现在看到的问题是dvAttacks.RowFilter 是改变结果,所以你需要通过使用线程锁使其线程安全:

   private static readonly object _lock = new object();

   public static string returnAttackDescription(string srAttackName, string srLang, string srCssClassName)
    {
        lock (_lock)
        {
            dvAttacks.RowFilter = "AttackName='" + srAttackName + "'";

            string srReturn = string.Format("<div class=\"{0}\" title=\"" +
                    "{0}<hr/>" +
                    "Type: {1}<br/>" +
                    "Category: {2}<br/>" +
                    "Base Power: {3}<br/>" +
                    "Accuracy: {4}<br/>" +
                    "Priority: {5}<br/>" +
                    "Effect: {6}\"></div>", srCssClassName, srAttackName,
                    dvAttacks[0]["AttackType"].ToString(),
                    dvAttacks[0]["AttackCategory"].ToString(),
                    dvAttacks[0]["BasePower"].ToString(),
                    dvAttacks[0]["Accuracy"].ToString(),
                    dvAttacks[0]["Priority"].ToString(), 
                    dvAttacks[0]["MoreFacts_" + srLang].ToString());

            return srReturn;
        }
    }

函数Descriptions()在您的应用程序启动时被调用,生成静态数据DataView dvAttacks,然后这些数据会一直保存在内存中,直到应用程序重新启动。您应用程序的每个池都有一组不同的此类数据。

在第二种解决方案中,您只读取它们而不影响DataView,因此您不会将它们更改为有任何冲突。就这样,工作正常,所有新内存在线程上都没有冲突。

这是线程中常见的private static DataView dvAttacks; 参数,它仅在您的应用程序启动时创建 - 之后您只有读取...但您不能在没有锁定的情况下更改它。

一个和两个的不同之处在于,第一个数据在过滤器内部发生变化,第二个你只是读取它们并将你需要的数据复制到新内存中,所以你只读取它们。第二个按原样工作。

这个数据视图会在第一次函数调用时被初始化吗

它在应用程序启动时和任何页面调用之前初始化。您可以使用Debug.Write 来查看。

【讨论】:

  • 第二个解决方案怎么样?数据将始终相同,因为它在重新启动时不会更改。你更喜欢哪一个?
  • @MonsterMMORPG 我不知道我更喜欢什么——也许把它们放在定时下,看看什么更快,然后选择更快的。我认为第一个更快。您可以使用Debug.Write() 来查看计时是如何工作的——例如调用Descriptions() 时。
  • 当行过滤时,DataView 状态正在改变。这实际上让我感到困惑。因为当许多线程进行行过滤时,它们如何获得单独的结果?
  • @MonsterMMORPG 我改变了它,你是对的,DataView 不能在没有锁定的情况下改变 - 你用 RowFilter 改变它,在第二种解决方案中你不改变它,你只阅读它跨度>
  • 我不得不说这里给出了很棒的答案:social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/…
猜你喜欢
  • 2012-12-09
  • 1970-01-01
  • 1970-01-01
  • 2016-07-16
  • 2010-11-08
  • 2011-11-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多