3

好简单的问题。在下面的类中做 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;
    }
}

时间:2019-04-01 标签:c#asp.net 4.0

4

1 回答 1

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;线程中常见的参数,并且仅在您的应用程序启动时创建 - 之后您只有读取......但您不能在没有锁定的情况下将其更改为ether inside。

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

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

它在应用程序启动的那一刻和任何页面调用之前初始化。您可以使用Debug.Write来检查这一点。

于 2012-12-11T22:04:40.927 回答