異なるスレッド間で共有される多値ディクショナリに似たグローバル オブジェクトが必要です。
オブジェクトを 1 回だけ作成し (たとえば、データベースからデータを取得する)、別のスレッドで使用したいと考えています。
オブジェクトは、追加のプロパティで簡単に拡張できる必要があります (現在、JobName と URL のみがあります)。
可能であれば、ロックを避けたいと思います。
次の問題に直面しています。
- 以下に表示されている現在のバージョンは、スレッド セーフではありません。
- 各キーに複数の値を許可するように Dictionary オブジェクトを拡張したため、ConcurrentDictionary を使用できません。
これは、簡単に変更できるオブジェクト構造です。
public struct JobData
{
public string JobName;
public string URL;
}
Dictionary オブジェクトを拡張して、各キーに複数の値を許可しました。
public class JobsDictionary : Dictionary<string, JobData>
{
public void Add(string key, string jobName, string url)
{
JobData data;
data.JobName = jobName;
data.URL = url;
this.Add(key, data);
}
}
スレッド間で共有される静的クラス。ご覧のとおり、特定のジョブに対して初めて呼び出されたときに、そのジョブの辞書エントリが作成されます。
たとえば、「earnings」に対して初めて呼び出されると、「earnings」ディクショナリ エントリが作成されます。これにより、スレッド セーフの問題が発生します。
public static class GlobalVar
{
private static JobsDictionary jobsDictionary = new JobsDictionary();
public static JobData Job(string jobCat)
{
if (jobsDictionary.ContainsKey(jobCat))
return jobsDictionary[jobCat];
else
{
String jobName;
String url = null;
//TODO: get the Data from the Database
switch (jobCat)
{
case "earnings":
jobName="EarningsWhispers";
url = "http://www.earningswhispers.com/stocks.asp?symbol={0}";
break;
case "stock":
jobName="YahooStock";
url = "http://finance.yahoo.com/q?s={0}";
break;
case "functions":
jobName = "Functions";
url = null;
break;
default:
jobName = null;
url = null;
break;
}
jobsDictionary.Add(jobCat, jobName, url);
return jobsDictionary[jobCat];
}
}
各スレッドで、次の方法で特定の Job プロパティを取得します。
//Get the Name
string JobName= GlobalVar.Job(jobName).JobName;
//Get the URL
string URL = string.Format((GlobalVar.Job(jobName).URL), sym);
一度「インスタンス化」されたカスタム辞書を作成するにはどうすればよいですか (静的であるため、適切な用語ではないことがわかっています...)、それはスレッドセーフですか?
ありがとう
アップデート
わかりました、これが新しいバージョンです。
switch ステートメントを削除し、すべてのディクショナリ項目を一度にロードすることで、コードを簡素化しました (とにかくすべてが必要です)。
このソリューションの利点は、一度だけロックされることです。つまり、ディクショナリ データが追加されたときです (ロックに入る最初のスレッドがディクショナリにデータを追加します)。スレッドが読み取りのためにディクショナリにアクセスする場合、ディクショナリはロックされません。
jobsDictionary は非公開であるため、スレッドセーフである必要があり、デッドロックが発生することはありません。
public static class GlobalVar
{
private static JobsDictionary jobsDictionary = new JobsDictionary();
public static JobData Job(string jobCat)
{
JobData result;
if (jobsDictionary.TryGetValue(jobCat, out result))
return result;
//if the jobsDictionary is not initialized yet...
lock (jobsDictionary)
{
if (jobsDictionary.Count == 0)
{
//TODO: get the Data from the Database
jobsDictionary.Add("earnings", "EarningsWhispers", "http://www.earningswhispers.com/stocks.asp?symbol={0}");
jobsDictionary.Add("stock", "YahooStock", "http://finance.yahoo.com/q?s={0}");
jobsDictionary.Add("functions", "Functions", null);
}
return jobsDictionary[jobCat];
}
}
}