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;
    }
}

2番目に考えられる解決策はこのスレッドセーフですか?

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

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その後、このデータは、アプリケーションが再起動するまで変更されることなくメモリに残ります。アプリケーションの各プールには、このデータの異なるセットがあります。

2番目のソリューションでは、に影響を与えずにそれらを読み取るだけDataViewなので、競合するように変更することはありません。したがって、そのままでは問題なく動作し、すべての新しいメモリがスレッドで競合することはありませんでした。

これはスレッド間で共通のパラメーターでありprivate static DataView dvAttacks;、これはアプリケーションの起動時にのみ作成されます。その後は読み取りのみが行われます...ただし、ロックなしで内部を変更しないでください。

1と2の違いは、最初はデータがフィルターを使用して内部で変更され、2番目はデータを読み取り、必要なデータを新しいメモリにコピーするため、読み取るだけであるということです。2つ目はそのまま動作します。

このデータビューは最初の関数呼び出しで初期化されますか

アプリケーションが起動した瞬間、ページ呼び出しの前に初期化されます。を使用しDebug.Writeてこれを確認できます。

于 2012-12-11T22:04:40.927 に答える