Reputation: 35
whenever i try to do any actions, i receive a deadlock, but i dont know why. The method redrawTable updating every clients registered in the server is my callback. When a player does an action like drawing a card, the server responses and returns the card to the players hand. While doing this, he notifies all the other players that someone did an action. Therefore, players will automatically update everything, not just based on actions, calling the asynch methods. Thus there are another requests to the server, and i think, thats what causes the deadlock. Since the method must come from the client, there is no other workaround i guess. Searching through the web, i came to something like this:
I found out a lot of useful codes there, but i can't implement them in the Visual Studio 2013, since the app i want is based on Windows 8/RT. Here is the code:
My Server
//interface ICallbackContract
public interface ICallbackContract
{
[OperationContract(IsOneWay = true)]
void redrawTable();
}
//interface IPlayer
[ServiceContract(SessionMode = SessionMode.Required,
CallbackContract=typeof(ICallbackContract))]
public interface IPlayer
{
[OperationContract(IsInitiating = true, IsTerminating = false, IsOneWay = true)]
void login(string name);
[OperationContract(IsInitiating = false, IsTerminating = false)]
bool drawCard();
[OperationContract]
Card returnDrawnCard();
[OperationContract]
void thrownCard(Card throw);
[OperationContract]
Card returnThrownCard(Card remove);
[OperationContract]
Card getTopCardOfDeck();
[OperationContract]
Dictionary<string, CardDeck> enemyCards();
[OperationContract]
List<Card> getRestDeck();
[OperationContract]
List<Card> getThrownStack();
}
//class Player
namespace CardGameServer
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession,
ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext=true)]
[CallbackBehavior(UseSynchronizationContext = false)]
public sealed class Player : IPlayer
{
public string Name { get; set; }
public static List<ICallbackContract> callBackList = new List<ICallbackContract>();
public void login(string name)
{
this.Name = name;
ICallbackContract callback =
OperationContext.Current.GetCallbackChannel<ICallbackContract>();
if (!callBackList.Contains(callback))
{
callBackList.Add(callback);
}
callBackList.ForEach(delegate(ICallbackContract player) { callback.redrawTable(); });
}
public Card returnDrawnCard()
{
//do something...
foreach (ICallbackContract callback in callBackList)
{
callback.redrawTable();
}
return true;
}
}
catch (ArgumentNullException)
{
throw;
}
return false;
}
My Client
namespace Cardgame.Client
{
public sealed partial class gamePage : Page, IPlayerCallback
{
InstanceContext context;
EndpointAddress address = new EndpointAddress(loginPage.serverAdresse);
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
DuplexChannelFactory<IPlayer> factory;
IPlayer myClient;
ObservableCollection<Card> Hand = new ObservableCollection<Card>();
ObservableCollection<Card> thrown = new ObservableCollection<Card>();
ObservableCollection<Card> Deck = new ObservableCollection<Card>();
ObservableCollection<Card> enemyDeck;
public gamePage()
{
this.InitializeComponent();
context = new InstanceContext(this);
factory = new DuplexChannelFactory<ISpieler>(context, binding, address);
myClient = factory.CreateChannel();
login();
throwable.ItemsSource = thrown;
lstCards.ItemsSource = Hand;
enemyLstCards.ItemsSource = enemyDeck;
}
private async void login()
{
await myClient.loginAsync(loginPage.username);
}
private async void drawCard_Tapped(object sender, TappedRoutedEventArgs e)
{
Hand.Add(await myClient.returnDrawnCardAsync());
}
public async void redrawTable()
{
//Update restOfDeck
.....
Deck = await myClient.getRestDeckAsync();
//Update thrownStack
.....
thrown = await myClient.getThrownStackAsync();
//Update Text
//Update enemyHand
.....
dictionary<string, CardDeck> myEnemy = await myClient.enemyCardsAsync();
}
Upvotes: 1
Views: 179
Reputation: 118
Linh2502, seeing your are using WCF and implementing a pub/sub model may I suggest you look into Juval Lowy's iDesign Publish-Subscribe Framework here:http://idesign.net/Downloads/GetDownload/2032
I believe you are specifically going to want to use transient subscriptions (in memory) is managed through the ISubscriptionService interface.
I believe this will help resolve your concurrency issues you are encountering.
Paul
Upvotes: 1