a lock that times out in time in a c# web service
My web service has this code
lock(typeof MyWebServiceClass)
Well i call a 3rd party unchangeable code and it never 开发者_Python百科returns. BOOM! BAM!
I am locked forever now and my web site crashes.
This never returns only happens once in a great while.
Is it possible to create a lock that times out? IE lock the code for 5 minutes then release the lock?
Instead of creating a timed lock, I would limit your third party request by putting it in a separate thread/task. Then, kick off the thread (or task if .NET 4.0 and TPL available to you) and join on the response with a timeout. If the join times out, then cancel the thread (or call the cancel token on the TPL task).
Is it possible to create a lock that times out?
Yes, this unpleasant situation is often refereed to as deadlock.
Usually it is good practice to lock on a static private object instead of locking on instance fields or the class itself:
private static object _syncRoot = new object();
and then:
lock(_syncRoot) {
}
If the 3rd party API has a cancellation mechanism then use that.
lock(typeof MyWebServiceClass)
{
if (ThirdPartyApiThatAcceptsTimeout(TimeSpan.FromMinutes(5)))
{
// The call was successful so proceed.
}
else
{
// The call timed out so bail out.
return;
}
}
However, I highly suspect that this API does not have a cancellation mechanism and so that is why you posed this question. If that is the case then this just got exponentially harder.
The naive approach would be to defer the API call to another thread. If the thread does not respond in a timely fashion then you can abort it.
lock(typeof MyWebServiceClass)
{
var thread = new Thread(
() =>
{
ThirdPartyApiThatCouldBlockIndefinitely();
});
thread.Start();
if (thread.Join(TimeSpan.FromMinutes(5))
{
// The call was successful so proceed.
}
else
{
// The call timed out so bail out.
thread.Abort();
return;
}
}
There are many problems with this though. First, there is no guarantee that the thread will accept the abort request. Since 2.0 there are special rules in the CLR that dictate when aborts can be injected into the thread. I believe the CLR will defer the injection while unmanaged code is executing. So if your API is unmanaged then the abort might not work. Also, aborts are voluntary since the thread could catch ThreadAbortException
and ignore it. Second, aborting is dangerous since the abort can be injected asynchronously. This makes it very difficult to guard against corrupting shared state. That is why the AppDomain is normally terminated after an abort.
The safest way to handle this is to put the API call into a separate process. You would have to use interprocess communication protocols like .NET Remoting, WCF, pipes, etc. to transfer data to/from the call which would be a real pain to maintain. But, it would be the safest since you can safely kill the process without the risk of corrupting the AppDomain of the caller.
I really feel for you because this problem is really hard to solve correctly.
精彩评论