wcfwindows-8.1datareaderstream-socket-client

Read method crashes after receiving a few packets


My application sends the users credentials to the server, if they are correct the server send a packet telling the client their credentials are wrong or right. After a couple of dummy tests, my client crashed due to this line of code;

            var count = await reader.LoadAsync(512);

Debugging shows that the count is 0,

But before crashing, I was able to send seven (7) dummy requests to the server. And the client was able to read seven (7) of the replies.

    private async void loginButtonEvent(object sender, RoutedEventArgs e)
    {
        //disable the button so the user can't spam the login button and flood packets 
        loginButton.IsEnabled = false;

        //if the user is connected to the server, then allow
        if(connected)
        {
            //get the stream
            DataWriter writer = new DataWriter(clientSocket.OutputStream);

            //custom class (like a packet IO, messafe frame/ framing
            MessageData md = new MessageData();
            md.MyUser = new User(usernameTextBox.Text, passwordTextBox.Text);
            md.MyType = MessageData.mType.LOGINREQUEST;
            //Serialize it into a string, thank you newton.Json
            string output = JsonConvert.SerializeObject(md);
            //write to the server
            writer.WriteString(output);
            //dedicate and push
            await writer.StoreAsync();
            //flush like you flush a toilet so it doesn't get clogged in the pipeline
            await writer.FlushAsync();
            //detatch the stream, not sure why?
            writer.DetachStream();

            //get the input stream
            DataReader reader = new DataReader(clientSocket.InputStream);
            //create string to hold the data
            string receivedData;
            //dynamically process the data
            reader.InputStreamOptions = InputStreamOptions.Partial;
            //store the bytes in count? why do we pass 512? What if I send a picture to the server and it is 1mb?
            var count = await reader.LoadAsync(512);
            //covert the byte to a string
            receivedData = reader.ReadString(count);
            //construct the md object into what the server sent
            md = JsonConvert.DeserializeObject<MessageData>(receivedData);
            switch (md.MyType)
            {
                case MessageData.mType.LOGINFAILED:
                    messageBox("Username or Password is wrong");
                    //Todo://
                    break;
                case MessageData.mType.LOGINSUCCESS:
                    messageBox("Logged");
                    //TODO: Go to login screen
                    break;
            }

            await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(1));


        }
        loginButton.IsEnabled = true;


    }

I tested this once more, and this time I was able to send twelve (12) packets to the server, and receive tweleve (12) packets that the client was able to intpretate.

Once again, the error lies in

            var count = await reader.LoadAsync(512);

An exception of type 'System.ObjectDisposedException' occurred in MobileApp.exe but was not handled in user code

Object Disposable Exception was unhanded by user code.


Solution

  • You're navigating into tricky waters when you call LoadAsync from within an async method. The LoadAsync method should only be called once from the UI thread. The method cannot be called again until after the LoadCompleted event is raised. Most likely your calling it a second time before the previous request is complete.

    Try switching out the offending await line to something like this:

    IAsyncOperation<int> asyncOp= reader.LoadAsync(512);
    asyncOp.AsTask().Wait();
    var count = asyncOp.GetResults();
    

    If you want a really long answer that goes into more detail, please see this answer: https://stackoverflow.com/a/9898995/3299157