我有一个帮助函数,它反序列化一个 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);
}
}
}