XML ファイルを逆シリアル化し、そこから c# オブジェクトを生成するヘルパー関数があります。
その後、オブジェクトはサーバーのメモリに追加されます。サーバーのメモリに何かを追加する唯一の方法は、この関数を使用することだけです。
public class DeserializeXmlHelper
{
public void DeserializeXml(Guid xml_Id, decimal version)
{
// heavy process here which takes about 3 seconds
}
}
この関数は、API メソッド (Asp.net MVC API で作成) を使用してさまざまなクライアントによって呼び出されています。
API を呼び出すときに、他の誰かが同じパラメーターで同じ関数を既に呼び出している場合、関数の実行を防ぐことはできますか?
このようなものですが、それが良い方法かどうかはわかりません。
public class DeserializeXmlHelper
{
private static readonly ConcurrentDictionary<string, object> _processes = new ConcurrentDictionary<string, object>();
public void DeserializeXml(Guid xml_Id, decimal version)
{
string processKey = string.Format("{0}_v{1}", xml_Id, version.ToString("#0.0"));
object processLocker = null;
if (_processes.TryGetValue(processKey, out processLocker) == false)
{
processLocker = new object();
_processes.TryAdd(processKey, processLocker);
}
lock (processLocker)
{
// heavy process here which takes about 3 seconds
_processes.TryRemove(processKey);
}
}
}
編集済み - 新バージョン
ティム・ロジャーの答えはうまくいっています。
ただし、最初の呼び出しが終了したときにのみ戻りたい場合は、次のようにすることはできますか? (ロックを追加する方法がわからないため、ConcurrentDictionaryを使用していますが、考え方は同じはずです)
public class DeserializeXmlHelper
{
private static readonly ConcurrentDictionary<string, string> _processes = new ConcurrentDictionary<string, string>();
public void DeserializeXml(Guid xml_Id, decimal version)
{
string _processKey = string.Format("{0}_v{1}", xml_Id, version.ToString("#0.0"));
string _processValue = null;
if (_processes.TryGetValue(_processKey, out _processValue) == true)
{
// function already called with the same parameters
do
{
System.Threading.Thread.Sleep(100);
}
while(_processes.TryGetValue(_processKey, out _processValue) == true)
return;
}
try
{
_processes.TryAdd(_processKey, _processValue);
var begin = "begin process";
System.Threading.Thread.Sleep(10000);
var end = "ending process";
}
finally
{
_processes.TryRemove(_processKey, out _processValue);
}
}
}