我有一个Web方法上传事务(ASMX Web服务),它接受XML文件,验证文件并将文件内容存储在SQL Server数据库中。我们注意到某些用户可以同时提交两次相同的文件。所以我们可以在我们的数据库中再次使用相同的代码(我们不能在数据库上使用唯一索引,或者在数据库级别执行任何操作,不要问我为什么)。我想我可以使用用户ID字符串上的锁定语句,但我不知道这是否会解决问题。或者如果我可以使用兑现对象来存储所有用户ID请求,并检查是否有来自同一用户ID的2个请求,我们将执行第一个请求并阻止第二个请求,并显示错误消息 ,因此如果有人有任何想法,请帮助阻止来自同一用户ID的多个请求到Web方法c#
1
A
回答
3
在字符串上阻塞是不好的。阻止你的网络服务器是不好的。
AsyncLocker
是我写的一个方便的类,它允许锁定任何类型的行为很好的字典中的键。它还需要异步进入临界部(相对于锁的正常封闭的行为)之前等待:
public class AsyncLocker<T>
{
private LazyDictionary<T, SemaphoreSlim> semaphoreDictionary =
new LazyDictionary<T, SemaphoreSlim>();
public async Task<IDisposable> LockAsync(T key)
{
var semaphore = semaphoreDictionary.GetOrAdd(key,() => new SemaphoreSlim(1,1));
await semaphore.WaitAsync();
return new ActionDisposable(() => semaphore.Release());
}
}
这取决于以下两个辅助类:
LazyDictionary:
public class LazyDictionary<TKey,TValue>
{
//here we use Lazy<TValue> as the value in the dictionary
//to guard against the fact the the initializer function
//in ConcurrentDictionary.AddOrGet *can*, under some conditions,
//run more than once per key, with the result of all but one of
//the runs being discarded.
//If this happens, only uninitialized
//Lazy values are discarded. Only the Lazy that actually
//made it into the dictionary is materialized by accessing
//its Value property.
private ConcurrentDictionary<TKey, Lazy<TValue>> dictionary =
new ConcurrentDictionary<TKey, Lazy<TValue>>();
public TValue GetOrAdd(TKey key, Func<TValue> valueGenerator)
{
var lazyValue = dictionary.GetOrAdd(key,
k => new Lazy<TValue>(valueGenerator));
return lazyValue.Value;
}
}
ActionDisposable:
public sealed class ActionDisposable:IDisposable
{
//useful for making arbitrary IDisposable instances
//that perform an Action when Dispose is called
//(after a using block, for instance)
private Action action;
public ActionDisposable(Action action)
{
this.action = action;
}
public void Dispose()
{
var action = this.action;
if(action != null)
{
action();
}
}
}
现在,如果你保持一个st这个地方的ATIC实例:
static AsyncLocker<string> userLock = new AsyncLocker<string>();
你可以用它在async
方法,利用LockAsync
的IDisposable
返回类型的美食写一个using
声明整齐地包装了关键部分:
using(await userLock.LockAsync(userId))
{
//user with userId only allowed in this section
//one at a time.
}
如果我们在进入之前需要等待,它会异步完成,释放线程来处理其他请求,而不是阻塞,直到等待结束,并且可能在加载时混乱服务器的性能。
当然,当你需要扩展到多个web服务器时,这种方法将不再起作用,并且你需要使用不同的方法(可能通过数据库)进行同步。
相关问题
- 1. 如何阻止来自同一IP的多个请求
- 2. Web服务和来自同一客户端的多个请求
- 3. 阻止来自同一服务器会话的相同请求
- 4. PHP cURL - 来自同一个'用户'的多个请求
- 5. Apache阻止多个请求?
- 6. PHP web-app deamon处理来自同一用户的多个请求
- 7. 来自域的阻止请求
- 8. 如何阻止用户查看来自AJAX请求的响应?
- 9. WCF来自同一客户端的多个请求
- 10. POST请求 - 跨来源请求阻止
- 11. phpbb3如何阻止来自不同地方的同一用户登录
- 12. 阻止请求
- 13. Nodejs一个请求阻止另一个请求
- 14. 一个有效的方法来阻止一个具体的网站发出POST请求到您的服务器?
- 15. Heroku阻止请求到URL
- 16. IIS7上的FastCGI ...来自同一用户会话的多个并发请求?
- 17. 发送一个POST请求到一个来自C#的URL请求#
- 18. Windows手机8异步Web请求与阻止用户触摸
- 19. 如何获得来自同一控制器的多个Web服务请求?
- 20. 改装call.enqueue阻止第一个请求
- 21. 防止来自同一用户名的多个连接
- 22. 如何阻止多个用户在PHP中同时访问单一方法?
- 23. 排队来自同一个HTTP客户端的servlet请求?
- 24. 阻止2个用户登录到同一个帐户
- 25. 同步来自多台机器的外部Web请求
- 26. 来自用户的每个请求调用一个新的getConnection()?
- 27. PHP - 阻止来自用户的
- 28. Servlet请求阻止
- 29. 如何阻止来自web浏览器和cURL等工具的请求?
- 30. 来自同一分支的多个请求
内容是否完全重复?是否允许重复?如果不是,您可以简单地丢弃重复请求(如果他们提交内容两次,但_far_足以避免锁定) –
切勿锁定字符串。永远。真。 http://stackoverflow.com/questions/12804879/is-it-ok-to-use-a-string-as-a-lock-object – spender