简体   繁体   中英

WCF Calling a service from a service

I haven't seen this answered yet, pretty simple setup...

Question: I'm getting a deadlock, I want to know how to avoid it, given my setup.

I have ServiceA, which implements IServiceA, and ServiceB, which implements IServiceB. Both services are marked as "perSession" and "re-entrant"...

IServiceA supports this method:

DataA GetDataA( );

IServiceB supports this method:

DataB GetDataB( );

in my app, I call ServiceA's GetDataA( ) method, and inside ServiceA's GetDataA method, it opens up a proxy connection to ServiceB, and calls GetDataB( ) .

GetDataB on the service end (not the client's end) executes correctly (debug log says so) but when it tries to return the data to ServiceA, it deadlocks.

I'm assuming this is because when I called into ServiceA from "user", it obtained the IO completion port "delivery lock" (or perhaps it's called the WCF per-session" lock. In any case, a lock is taken. I'm assuming that when ServiceB's GetDataB( ) is attempting to return the value, what's it's really done is flipped around the channel and is trying to call a receive method on ServiceA, which needs the lock and deadlocks.

in every question I've read so far where people ask "is it okay to chain one service from another", every (stupid) answer has been, "sure! go ahead! nothing to it! services don't know if they're being called by normal .NET code or if they're being called from another service!". Annoying. There certainly "is something to it", even if it's a little tiny bit trivial.

I've read that I can't mark methods that return values as "one way". And marking them as "re-entrant"... should that work or not? I know if in my service, I call a callback, the lock is silently released. What if I call another service? is WCF smart enough to release the lock in that case as well?

I could go mark my services as "multiple" instead of "re-entrant", but I'm wondering (a) is the deadlock really from what I think it is, or could it be from something else, and (b) is there a better way around this?

Figured it out. And I must be honest, I started learning WCF by reading MSDN, but it droned on and on, so I moved on to some WCF online books (By Lowy & others). I should have kept reading MSDN.

I got this answer from one of the devs on the WCF team:

"The lock isn't happening at the transport layer, it's happening at the instance context layer. When a client in service A makes an outgoing request-reply call to service B, the reply isn't going back to service A, it's going back to the client for service B that service A is using."

That makes sense. But in addition to that information, I also learned this:

"If you use WCF services to call out of any method (call out = callback or another WCF service), and you're marked as "reenttrant", WCF will free the InstanceLock".

(Thus, the deadlock I'm seeing above is (probably) my own fault...)

I found this tidbit here:

https://channel9.msdn.com/Forums/TechOff/254330-WCF-ConcurrencyModeReentrant-Confusion

And that led me to this valuable article here:

https://msdn.microsoft.com/en-us/library/aa395214(v=vs.110).aspx

Quote: In case of Reentrant mode, the InstanceContext is unlocked just before the service makes an OUTGOING CALL thereby allowing the subsequent call, (which can be reentrant as demonstrated in the sample) to get the lock next time it comes in to the service.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM