Search code examples
c#streamingrpc

Why do I get this exception (gRCP)


I try to do a BlackJack game in gRPC to practice, but I don't understand this stream transfer.

Task(Server):

public async Task Deal(Amount dealAmount, IServerStreamWriter<Card> responseStream, ServerCallContext context)
    {
        this.dealAmount = int.Parse(dealAmount.ToString());
        if (deck.Count < 17)
        {
            deck.Clear();
            DeckRead();
            Shuffle();
        }

        FirstDeal();

        Card temp = new Card();
        temp.Card_ = player[0];
        await responseStream.WriteAsync(temp);
        temp.Card_ = player[1];
        await responseStream.WriteAsync(temp);
        temp.Card_ = dealer[0];
        await responseStream.WriteAsync(temp);
    }

Client:

private async void btDeal_Click(object sender, EventArgs e)
    {
        Amount dAmount = new Amount();
        dAmount.Amount_ = Convert.ToInt32(udDeal.Value);
        string newCard;

        using (var call = client.Deal(dAmount))
        {
            var responseStream = call.ResponseStream;
            int y = 0;
            while (await responseStream.MoveNext())
            {
                newCard = responseStream.Current.ToString();

                if(y == 3)
                {
                    dealer.Add(newCard);
                }
                else
                {
                    player.Add(newCard);
                    y++;
                }
            }
        }

        dealerCards[0].Load(string.Format("Images/cards/{0}.png", dealer[0]));
        dealerCards[1].Load(string.Format("Images/cards/Back/gray_back.png"));
        playerCards[0].Load(string.Format("Images/cards/{0}.png", player[0]));
        playerCards[1].Load(string.Format("Images/cards/{0}.png", player[1]));

        lblDealerAmount.Text = int.Parse(dealer[0].Substring(0, 2)).ToString();
        lblPlayerAmount.Text = PlayerAmount().ToString();

        money = money - dealAmount;
        lblAmount.Text = money.ToString();
        btDeal.Enabled = false;
    }

proto:

rpc Deal(Amount) returns (stream Card) {}

message Card {
   string card=1;
}

message Amount {
  int32 amount=1;
}

I know that this is not the cleanest code ever, but for now I just want to understand how gRCP is working. So this task would deal the first four card, two to the player, two to the dealer but one of the dealer's card with the back, so the client will get three Card (2 of his card and 1 is the dealer's card what he can see).

First of all, I get an exception at while (await responseStream.MoveNext()) , because of the input parameters, but don't know what is the wrong.

RpcException:

An exception of type 'Grpc.Core.RpcException' occurred in mscorlib.dll but was not handled in user code Additional information: Status(StatusCode=Unknown, Detail="Exception was thrown by handler.")

In the server's console:

E02/01/2019 13:46:47 Grpc.Core.Internal.ServerStreamingServerCallHandler`2 Exception occured in handler. System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Int32.Parse(String s)
   at BlackJackServer.BJS.<Deal>d__14.MoveNext() in C:\Users\tesa3\Desktop\GRPC BEAD\grpc\grpc-master\examples\csharp\BlackJack\BlackJackServer\Program.cs:line 108
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at Grpc.Core.Internal.ServerStreamingServerCallHandler`2.<HandleCall>d__0.MoveNext()

From the otherside I dont know that I use WriteAsync properly in this case. I mean I exactly know the client will get three string. Can I just read the current, and then MoveNext and read again and so on?


Solution

  • This looks like a problem in your code that's mostly unrelated to gRPC.

    From the error message it's obvious that it's happening inside the server-side handler. Let's take a look there.

    The very first line there is int.Parse(dealAmount.ToString());, the "dealAmount" is a protocol buffer message, and ToString() gives its JSON representation (e.g. something like { "Value": 123 } or so). This clearly has not the format that int.Parse can accept (hence the exception "System.FormatException: Input string was not in a correct format.").

    Converting to a protobuf message to string and then trying to parse makes no sense - the generated "Amount" class already gives you access to all the fields you need, with the right type.