WCF locks due to callback even when IsOneWay callback

new to WCF.

I have a client that blocks when the WCF service is called.

The service will call a callback for the client during a call marked as IsOneWay. I confirmed that the service is not blocking the callback.

Then, the client immediately calls the same service again (in a closed loop), but did not complete the callback. The client then blocks (and the breakpoint on the service side never starts).

So, to repeat:

CLIENT SERVICE Call service -----------------------> (service breakpoint triggers) (waiting for dispatch thread) <------ Invoke callback (IsOneWay - doesn't block) Service returns Call service again immediately -----? (service breakpoint doesn't trigger) (deadlock) 

I assume the callback captured some WCF lock on the client side, and then the second service call from the client also wants to block, so the results are deadlocks. But this is just an assumption.

I read about ConcurrencyMode, but I can’t decide which mode to use or where to place it, because I don’t 100% understand what is happening and what exactly is being blocked.

I would also prefer that all callbacks be served by the send stream, if possible, as this simplifies the code.

Can any WCF experts shed light on what is happening here?

Many thanks

+7
source share
2 answers

Well, I think I discussed this.

WCF uses single-threaded by default. All calls and callbacks are combined into a single thread (or SynchronizationContext, to be more precise).

My application is a single-threaded WPF application, so the SynchronizationContext is set to the send stream.

When the callback arrives, it tries to transfer the call to the send stream, which, of course, is blocked during the initial call to the service. I don’t understand that this is locked for sure, but obviously there is a global lock that he is trying to get before waiting for the sending stream.

When the send thread then calls the service again, it blocks this global lock.

Two ways:

1) Create a service proxy in another thread. All calls will be processed through this thread instead, and it does not matter that the send thread is blocked.

2) Apply the [CallbackBehavior (UseSynchronizationContext = false)] attribute to the client class that implements the callback. This means that WCF ignores the synchronization context when the callback arrives, and it will serve it in any available thread.

I went with 2. Obviously, this means I need to mobilize callbacks that could update the GUI for the send thread myself, but fortunately my callback implementation is a small shell, so I just do _dispatcher.BeginInvoke ( ) in each callback method for Marshal ASYNCHRONOUSLY. Then the sending stream will be serviced when it gets the chance that I wanted in the first place.

+20
source

The sequence you depicted resembles a synchronous call. If in an asynchronous call the sequence will look like this:

 Client Server Call service --------------->ProcessRequest(1) //Your for loop for instance. Call service --------------->ProcessRequest(2) Call service --------------->ProcessRequest(3) Call service --------------->ProcessRequest(4) Call service --------------->ProcessRequest(5) Callback awake <---------------Response1 //Responses tends to pour in... Callback awake <---------------Response2 Callback awake <---------------Response3 Callback awake <---------------Response4... 

In each case of each asynchronous web service call, the system creates a separate I / O stream (IOCP stream) and processes the request. In this rarely you will find a dead end.

I found this method, even when called inside a loop, work very well.

You can, for example, register for the .OnProcessComplete event, and then call the ProcessCompleteAsync method.

0
source

All Articles