Skip to content

WCF’de Callback Method’lar için tuhaf bir anekdot

Yine blog’u yanlızlığa terkettiğim bir ayın ardından ufak bir sorun ve çözüm ile beraberiz. Dün akşam saatlerinden bugün sabaha kadar bir türlü içinden çıkamadığım bir sorunun kaynağını absürd bir biçimde buldum, sizlerle paylaşmak isterim sayın seyirciler.

Şimdi WCF ile birlikte callback yapan bir sistem kurduk diyelim. Bu sistemde ana operation contract olarak subscribe isimli bir method’umuz var. Bu method cağırıldığında bağlı olan ve kanalı halen açık olan istemcilerdeki subscribed isimli callback methodu cağrılıyor. İçerik şu şekilde

Private Sub Subscribe(ByVal context As OperationContext)
	If Not subs.Keys.Contains(context.SessionId) Then
		AddHandler context.Channel.Faulted, AddressOf ChannelStateChange
		subs.Add(context.SessionId, context)
	Else
		subs(context.SessionId) = context
	End If

	InvokeCallback(False, "Subscribed", context.SessionId)
End Sub

Görülebileceği üzere yeni gelen istemciyi öncelikle listeye ekleyip sonra bu listeyi baz alarak geri dönüşleri yapıyor. Oluşan sorun ise söyle; bu methodu cağıran istemci ve sunucu birlikte kilitlenip cevap veremez hale düşmekte ve timeout olana kadar öyle kalmakta.

Sorunun kaynağı şu; eğer istemciler birer windows forms uygulaması ise ve bu method çağrılırken ek bir thread kullanılmıyorsa tüm UI thread’ı bu fonksiyonun dönüşünü bekleyecektir. Bu fonksiyon sonlanıp dönüş yapmadan önce sırayla tüm istemcilere callback yapmakta ve bu callback’lerin cevablarını sunucu tarafta beklemekte. Kilitlenmiş halde subscribe methodunun sonlanmasını bekleyen bu yeni katılan istemci callback’e cevap veremeyeceğinden sunucu tarafı da kilitlemiş bulunuyor.

Daha basit olarak anlatmak gerekirse katılma işlemi esnasında cevap bekleyen istemci aslında aynı anda yeni katılanın callback çağrımına cevap vermesi gerektiğinden tüm sistem bir anda deadlock durumuna geçip timeout’a düşüveriyor.

Çözüm basit ya subscribe method’unu oneway olarak tanımlamak ya da bu cağrımı UI thread’ı yerine ek bir thread’a yaptırmak. Bu sayede callback yapıldığında yeni katılan istemci bu çağrıma cevap verecek ve tüm sistemin kilitlenmesine sebep olmayacaktır. Bir başka çözüm ise subscribe esnasında callback’leri yaparken yeni katılan istemciye callback yapmamakta olabilir.

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*