async method doesn't execute all the way through - c#

I have a method that adds some data to my database, it worked fine a while ago but now it has just stopped working.
I found out with debugging that my async method gets called but then just stops in the middle and the Answers are never getting added:
private async Task CreateNewQuestion()
{
if (newQuestion.QuestionType is null)
{
noType = true;
return;
}
else if (Answers.Count == 0)
{
noAnswer = true;
return;
}
else if (newQuestion.QuestionType is not null)
{
List<Question> questioncount = new List<Question>();
questioncount = await questionRepo.GetQuestionByQuizId(QuizId);
_order = questioncount.Count + 1;
newQuestion.QuestionOrderId = _order;
newQuestion.AnswerType = _answerType;
newQuestion.QuestionUrl = _questionUrlConverted;
await questionRepo.AddQuestionWithAnswers(newQuestion, Answers); <-- THIS IS WHERE THE METHOD GETS CALLED
noType = false;
questions = await questionRepo.GetQuestionByQuizId(QuizId);
var quiz = quizRepo.GetQuizById(QuizId);
Navigation.NavigateTo($"/Quiz/AddQuestionWithId/{QuizId}", true);
}
}
and here is the method:
public async Task AddQuestionWithAnswers(Question newQuestion, List<Answer> answers)
{
if(newQuestion is not null && answers.Count > 0)
{
_context.Questions.Add(newQuestion);
await _context.SaveChangesAsync(); <-- THIS IS WHERE IT JUST STOPS TO EXECUTE
var answerQuestionItem = await GetQuestionById(newQuestion.QuestionId);
if(answerQuestionItem is not null)
{
foreach(var answer in answers)
{
answer.Question = answerQuestionItem;
_context.Answers.Add(answer);
await _context.SaveChangesAsync();
}
}
}
}
It also doesn't even go back to the method that called the method, just to my razor component and nothing happens.
Any ideas how I can fix this?

Related

Program come out of function without executing await

I'm using Two await function in my program, and first one is working flawlessly but on encountering second await, my program comes out of function without executing that awaitable function and any line after that.
Not giving error and not even crashing.
Tried "wait()", "Running on main thread", "Task Run", "Threading Sleep"..
here a snippet of the code along
private async void Btn_Clicked(object sender, EventArgs e)
{
//this statement works perfectly fine
var status = await CrossPermissions.Current.RequestPermissionAsync<LocationPermission>();
//on debugging i found out it return out of function at this point without executing
var check = await CrossPermissions.Current.RequestPermissionAsync<CameraPermission>();
//None of the code is executed
Console.WriteLine("Granted");
Console.WriteLine("Granted");
}
You try to use the below method :
private async void Btn_Clicked(object sender, EventArgs e)
{
await GetPermissions();
}
public static async Task<bool> GetPermissions()
{
bool permissionsGranted = true;
var permissionsStartList = new List<Permission>()
{
Permission.Location,
Permission.Camera,
};
var permissionsNeededList = new List<Permission>();
try
{
foreach (var permission in permissionsStartList)
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(permission);
if (status != Plugin.Permissions.Abstractions.PermissionStatus.Granted)
{
permissionsNeededList.Add(permission);
}
}
}
catch (Exception ex)
{
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(permissionsNeededList.ToArray());
try
{
foreach (var permission in permissionsNeededList)
{
var status = Plugin.Permissions.Abstractions.PermissionStatus.Unknown;
//Best practice to always check that the key exists
if (results.ContainsKey(permission))
status = results[permission];
if (status == Plugin.Permissions.Abstractions.PermissionStatus.Granted || status == Plugin.Permissions.Abstractions.PermissionStatus.Unknown)
{
permissionsGranted = true;
}
else
{
permissionsGranted = false;
break;
}
}
}
catch (Exception ex)
{
}
return permissionsGranted;
}

How can I run many asynchronous methods all together?

I want to run my asynchronous methods GetPlayerCountryData() and GetPlayerTagsData() all together to save time instead of starting the next method only after the previous has completed. But I don't know how to do that.
https://jeremylindsayni.wordpress.com/2019/03/11/using-async-await-and-task-whenall-to-improve-the-overall-speed-of-your-c-code/
I have read this tutorial but I don't know how to use await Task.WhenAll() in my code.
In addition, I want to execute the line AllMethodsCompleted = true; after all my asynchronous methods have been completed successfully. Should I use await Task.WhenAll() in this situation?
How can I only set AllMethodsCompleted = true if all my asynchronous methods completed successfully? Is it possible to find out if (result.Error != null) or an exception occurred in one of the asynchronous methods before setting AllMethodsCompleted = true ?
string PlayerDeviceId = "";
private void RegisterGuestPlayFabAccount()
{
PlayerDeviceId = ReturnMobileID();
var requestIOS = new LoginWithIOSDeviceIDRequest { DeviceId = PlayerDeviceId, CreateAccount = true };
var loginTask = PlayFabClientAPI.LoginWithIOSDeviceIDAsync(requestIOS);
loginTask.ContinueWith(OnPlayFabRegisterGuestAccountComplete);
}
private void OnPlayFabRegisterGuestAccountComplete(Task<PlayFabResult<LoginResult>> task)
{
if (task.Result.Result != null)
{
PlayerAccountDetails();
}
if (task.Result.Error != null)
{
OnPlayFabError(task.Result.Error);
}
}
bool AllMethodsCompleted = false;
public async void PlayerAccountDetails()
{
await GetPlayerCountryData();
await GetPlayerTagsData();
AllMethodsCompleted = true;
}
private async Task GetPlayerTagsData()
{
var resultprofile = await PlayFabServerAPI.GetPlayerTagsAsync(new PlayFab.ServerModels.GetPlayerTagsRequest()
{
PlayFabId = PlayerPlayFabID
});
if (resultprofile.Error != null)
OnPlayFabError(result.Error);
else
{
if ((resultprofile.Result != null) && (resultprofile.Result.Tags.Count() > 0))
CurrentPlayerTag = resultprofile.Result.Tags[0].ToString();
}
}
private async Task GetPlayerCountryData()
{
var resultprofile = await PlayFabClientAPI.GetUserDataAsync(new PlayFab.ClientModels.GetUserDataRequest()
{
PlayFabId = PlayerPlayFabID,
Keys = null
});
if (resultprofile.Error != null)
OnPlayFabError(result.Error);
else
{
if (resultprofile.Result.Data == null || !resultprofile.Result.Data.ContainsKey("Country") || !resultprofile.Result.Data.ContainsKey("City"))
Console.WriteLine("No Country/City");
else
{
PlayerCountry = resultprofile.Result.Data["Country"].Value);
PlayerCity = resultprofile.Result.Data["City"].Value);
}
}
}
public async Task PlayerAccountDetails()
{
var playerCountryData = GetPlayerCountryData());
var playerTagsData = GetPlayerTagsData());
await Task.WhenAll(playerCountryData, playerTagsData);
AllMethodsCompleted = true;
}
Here is the method you are in query about and running the 2 methods in async waiting for each to finish then moving on. They just needed to be assigned to a task variable.

Set a WPF Mahapps Progress Dialog

I'm trying to replace my ProgressBar to a Progress Dialog using Mahapps.
So I started writing this:
private void btnClick(object sender, RoutedEventArgs e)
{
ConfRelais();
}
public async void ConfRelais()
{
var controller = await this.ShowProgressAsync("hey", "hoy");
controller.Maximum = 128;
while (flag == 0)
{
string data = RelayBoard_Port.ReadTo("\r\n");
if (data == "ok") { controller.SetMessage("Done Process");
flag = 1; }
else { controller.SetProgress(Int32.Parse(data)); }
}
await controller.CloseAsync();
}
But the progress dialog only displays when it's over.. As I'm still a beginner in c# maybe I'm missing some importants points to setup that kind of function.
You should execute the loop on a background thread:
public async void ConfRelais()
{
var controller = await this.ShowProgressAsync("hey", "hoy");
controller.Maximum = 128;
await Task.Run(() =>
{
while (flag == 0)
{
string data = RelayBoard_Port.ReadTo("\r\n");
if (data == "ok")
{
controller.SetMessage("Done Process");
flag = 1;
}
else { controller.SetProgress(Int32.Parse(data)); }
}
});
await controller.CloseAsync();
}
A single thread cannot both update the UI and execute your loop simultaneously.
You also don't really need a flag. You could just break out of the loop when you receive "ok":
while (true)
{
string data = RelayBoard_Port.ReadTo("\r\n");
if (data == "ok")
{
controller.SetMessage("Done Process");
break;
}
else { controller.SetProgress(Int32.Parse(data)); }
}

Why is this display alert not working? it worked fine when i tried it in a button Clicked event, but its not working in a Function

1 ) Its a weather Api and i want it to display no internet connection when there is no internet connected to the device.
public async void method()
{
Indicator.IsRunning = true;
Weather weather = await GetWeather(nameplace.Text);
if (weather != null)
{
if (weather.message == "city not found")
{
txtLocation.Text = "city not found";
}
else
{
Location.Text = weather.Title;
Temperature.Text = weather.Temperature;
Temperature.Text += "°";
txtWind.Text = weather.Wind;
Humidity.Text = weather.Humidity;
Sunrise.Text = weather.Sunrise;
Sunset.Text = weather.Sunset;
double condition = Convert.ToDouble(weather.Condition);
if (condition >= 0 && condition < 30)
{
Condition.Text = "Clear Sky";
}
else if (condition >= 30)
{
Condition.Text = "Cloudy";
}
}
}
else
{
await DisplayAlert("Alert", "Sorry ! No internet connection","Ok")`
}
}
3) // Below in a getservice function i have
if (Plugin.Connectivity.CrossConnectivity.Current.IsConnected)
{
var response = await client.GetAsync(QueryString);
// pQueryString is the http request
_httpStatusCode = response.StatusCode.ToString();
if (response == null)
{
return "Sorry! No record Found.";
}
else if (response != null)
{
string json = response.Content.ReadAsStringAsync().Result;
data = JsonConvert.DeserializeObject(json);
}
}
else
{
data = null;
}
return data;
4) i have return null and put a condition in there so that it can display an alert saying no internet connection
It is possible that your async void method messes with the Thread context, and that you end up not calling your code in the ui thread.
You could try this:
Xamarin.Forms.Device.BeginInvokeOnMainThread(
() => DisplayAlert("Alert", "Sorry ! No internet connection","Ok"));
Also it's a bad design to put UI code in your service layer.
Your should call your DisplayAlert code in your ViewModel not in your service.

How the async Task return conditionally

Hi am trying to return for an async method task conditionally. Below is the way I tried.
public string DoMessage(MyObj obj)
{
string returnStatus = "Processing...";
var storageAccount = CloudStorageAccount.DevelopmentStorageAccount;
var queueClient = storageAccount.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference(ConfigurationManager.AppSettings["QueueName"]);
if (queue.CreateIfNotExists()) {
}
var msg = CloudQueueMessageExtensions.Serialize(obj);
queue.AddMessage(msg);
//Task processTask = RunMessageProces();
var t = Task.Run(() => RunMessageProces());
t.Wait();
return returnStatus;
}
private async Task<string> RunMessageProces()
{
statusProcess = "Your message successfully inserted in process queue.";
await Task.Run(() => {
lock (_oQueue)
{
if (flagProcessing == true) //return when queue processing alredy started
{
return statusProcess; //Error ..??? how to return
}
flagProcessing = true; //else start processing the queue till there are messages.
}
});
statusProcess = ProcessMyMessage();
return statusProcess;
}
private string ProcessMyMessage() {...}
What I am missing? How to return string in between conditionally under async method that too lie inside await lock anonymous block(?). I do async in task as Do Message is flooded with lot of calls simultaneously due to exposed part of a service.
I am assuming you are asking how to access the returned value from the task.
private async Task<string> RunMessageProces()
{
var statusProcess = "Your message successfully inserted in process queue.";
var retValue = await Task.Run(() =>
{
lock (_oQueue)
{
if (flagProcessing == true) //return when queue processing alredy started
{
return "Error"; // or some such error indicator
}
flagProcessing = true; //else start processing the queue till there are messages.
}
return string.Empty; // return a string here too....
});
// if( retValue == "Error" ) { return "Error" }
statusProcess = ProcessMyMessage();
return statusProcess;
}

Categories