Сбой метода чтения после получения нескольких пакетов
Мое приложение отправляет учетные данные пользователей на сервер, если они верны, сервер отправляет пакет, сообщая клиенту, что его учетные данные неверны или верны. После нескольких фиктивных тестов мой клиент завис из-за этой строки кода;
var count = await reader.LoadAsync(512);
Отладка показывает, что счетчик равен 0,
Но перед сбоем я смог отправить семь (7) фиктивных запросов на сервер. И клиент смог прочитать семь (7) ответов.
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;
}
Я проверил это еще раз, и на этот раз я смог отправить двенадцать (12) пакетов на сервер и получить двенадцать (12) пакетов, которые клиент смог интерпретировать.
Еще раз, ошибка заключается в
var count = await reader.LoadAsync(512);
Исключение типа "System.ObjectDisposedException" произошло в MobileApp.exe, но не было обработано в коде пользователя
Исключение одноразового использования объекта не было обработано кодом пользователя.
2 ответа
Вы переходите в сложные воды, когда вызываете LoadAsync из асинхронного метода. Метод LoadAsync должен вызываться только один раз из потока пользовательского интерфейса. Метод не может быть вызван снова, пока не будет вызвано событие LoadCompleted. Скорее всего, вы звоните во второй раз, прежде чем предыдущий запрос будет завершен.
Попробуйте переключить оскорбительную строку ожидания на что-то вроде этого:
IAsyncOperation<int> asyncOp= reader.LoadAsync(512);
asyncOp.AsTask().Wait();
var count = asyncOp.GetResults();
Если вы хотите получить очень длинный ответ, который будет более подробным, посмотрите этот ответ: /questions/44232435/ispolzuyutsya-li-v-novyih-klyuchevyih-slovah-c-50-async-i-await-neskolko-yader/44232458#44232458
//start a new task!
Task t = new Task(ListenForMessage);
//if the currrent task is not completed, then return
//this means it wont calll var count = await reader.LoadAsync(512); I.E the devil
if (!t.IsCompleted)
return;
//else if the task is completed, then run it!
t.RunSynchronously();
Благодаря Ageonix, я смог прийти к такому выводу благодаря его ответу, который вызвал эту реализацию.
Кредит дается там, где кредит должен.