WCF Callback-deadlock
Rannte ich in ein problem mit einem WCF-Dienst ruft eine callback Methode auf dem client. Zuerst der service:
[ServiceContract(
SessionMode = SessionMode.Required,
CallbackContract = typeof(IMarketObserver))]
public interface IServer
{
...
[OperationContract]
[FaultContractAttribute(typeof(WCFFaultDetail))]
bool NotifyOnMarket(EnumMarkets marketID);
...
}
Service-Implementierung:
[ServiceBehavior(
InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false)]
public sealed class Platform : IServer
{
...
public bool NotifyOnMarket(EnumMarkets marketID)
{
try
{
IMarketObserver callback = OperationContext.Current.GetCallbackChannel<IMarketObserver>();
if (subscribers.Contains(callback) == false)
{
subscribers.Add(callback);
}
}
catch
{
return false;
}
//This call may cause a call to the callback method SendMarketData()!!
callSomeMethod();
return exchangeProxy.IsMarketIDValid();
}
Den rückrufvertrag:
public interface IMarketObserver
{
[OperationContract(IsOneWay = true)]
void SendMarketData(MarketData marketData);
}
Die client-Implementierung dieses callback ist:
[CallbackBehavior(
ConcurrencyMode = ConcurrencyMode.Multiple,
UseSynchronizationContext = false)]
public class MarketBase :
IServerCallback
{
protected IService serviceProxy;
public void SendMarketData(MarketData marketData)
{
//Do something
}
private void NotifyOnMarkets()
{
foreach (EnumMarkets item in observedMarkets)
{
try
{
bool res = serviceProxy.NotifyOnMarket(item);
}
catch (Exception e)
{
...
}
}
}
Tritt das problem beim Aufruf NotifyOnMarkets() mit der foreach-Schleife.
Wenn es nur ein Element in der observedMarkets Liste, so gibt es genau einen Aufruf der service ist NotifyOnMarket () - Methode, und alles ist in Ordnung.
Aber wenn observedMarkets enthält mehr als ein Element, dann NotifyOnMarket() wird aufgerufen, viele Male mit einer hohen Frequenz auf den server.
Die Umsetzung der NotifyOnMarket() auf dem server wird eine Methode aufgerufen, die wiederum ruft dann die callback-Methode SendMarketData(ich kommentierte diese Tatsache).
In den Spuren, die ich sehen kann, dass serviceProxy.NotifyOnMarket(item); nicht zurück, auf ein zweites Element, ein timeout Auftritt.
Auf dem server der Seite, mehrere Anrufe zu NotifyOnMarket() werden korrekt behandelt und die Methode wird verlassen. Aber wie oben schon gesagt, wird das boolean-Ergebnis wird nicht zeigen, bis auf dem client(timeout).
Außerdem, kann man sehen, dass auf der server-Seite der Rückruf aufgerufen wird(es ist one-way, so dass keine Antwort wird zurückgegeben), aber auf der client-Seite geschieht nichts, da die callback-Implementierung ist nicht genannt.
Mein Fazit ist, dass irgendeine Art von deadlock aufgetreten ist und dies vielleicht aufgrund der client-Instanz, die Schlösser selbst und so kann der server nicht Aufruf der callback-Methode.
Ist es, besser zu trennen die Instanz-Kontext-Klasse von der Klasse, die auch die Durchführung von service-Aufrufe? Wenn ja, warum?
Dank für die Beratung, die
Jürgen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ihre Frage: Warum muss es auf einem anderen thread?
Lesen Sie die Ende WCF Duplex-Messaging:
Du machst es richtig, indem Sie es auf Mehrere oder Re-entrant (beide arbeiten, aber re-Teilnehmer force 1 thread zu einem Zeitpunkt, und mehrere werden, damit mehrere threads geben Sie Ihren service auf einmal). Ich persönlich würde es als "re-entrant", es sei denn, du brauchst mehrere threads Eingabe Ihres service auf einmal.
Schrieb ich einfach eine test-Fall auf meinem Rechner hier, nach Ihrem Beispiel, und es hat Prima funktioniert. Ich denke, Ihr IIS-Umsetzung (zurück in '11) hatte einen Fehler. Unmöglich, testen Sie, jetzt.