How to keep the processing time within OnSleep()? - forms

I am currently developing a Xamarin Forms UWP application. I am trying to save data when OnSleep () is called when the application ends, but it ends in the middle of the process. How can I continue processing to the end?
I tried how much processing time can be secured in OnSleep ().
in App.xaml.cs
protected override async void OnSleep()
{
// Handle when your app sleeps
Tracer.WriteLine("OnSleep In");
await Task.Delay(2000);
Tracer.WriteLine("OnSleep Out");
}
Expected result
14:25:21.414 OnSleep In
14:25:23.414 OnSleep Out
Actual result (never comes OnSleep Out)
14:25:21.414 OnSleep In
14:25:21.827 OnSleep In
program ended

Related

How to get ACRA to stop app when exception is not in main activity?

I want my app to stop when ACRA detects and reports an uncaught exception - normal ACRA behavior. This is not working when the exception happens in an activity that is not the main activity.
After fighting this in my actual app, I created a very simple app that uses ACRA, and allows me to force an exception in either the main activity, or a second one that can be started from the first. I am testing with a MinSDK of 26. The app is in Java and has only enough code to generate this test.
An exception in the first activity produces the desired result (as determined from logcat and the screen):
On button touch, main activity generates an exception
ACRA catches the exception:
ACRA starts another application process
the first process ends
the second process does ACRA processing
the second process ends
However, running again, but with the exception in the second activity (with the first still on the task stack), results in:
On button touch, main activity starts second activity
On button touch, second activity generates an exception
ACRA starts another application process
First process ends
ACRA processes in the second process (also using this code base)
meanwhile Android starts yet a third process - this is the problem
The second process finishes
The third process displays the main activity screen, and waits
What seems to be happening is that Android is detecting that there is an activity left on the stack, and is starting a new process to bring that one forward.
But, ACRA should be stopping this.
Is this an ACRA problem? In any case, ideas on how to prevent it?
*NOTE:
In my tests, I am using touch events on a bottom navigation bar to generate a divide by zero exception.
The order of when ACRA finishes and the third process starts is indeterminate, as far as I can tell. It is also probably irrelevant.
Test results are from watching the screen, and logcat. Important evens are logged using the Log class.
Below is a snippet from the main activity that shows the button processing, and the exception generation. The second activity is similar.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Context context = this.getApplicationContext();
setContentView(R.layout.activity_main);
Log.i(MyApp.TAG, "MainActivity.onCreate() - pid:"+android.os.Process.myPid());
mTextMessage = findViewById(R.id.message);
BottomNavigationView navigation = findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener((item) -> {
switch (item.getItemId()) {
case R.id.navigation_home:
int i = 0;
Log.i(MyApp.TAG, "Throwing exception in main activity");
Log.i(MyApp.TAG, "This shouldn't show up" + 3 / i);
return true;
case R.id.navigation_dashboard:
Log.i(MyApp.TAG, "Starting Activity2");
startActivity(new Intent(context, Activity2.class));
return true;
case R.id.navigation_notifications:
mTextMessage.setText(R.string.title_notifications);
return true;
}
return false;
});
This is a bug in ACRA, fixed by this PR, which will be included in the next release (5.3.0).

Async/Await/then in Dart/Flutter

I have a flutter application where I am using the SQFLITE plugin to fetch data from SQLite DB. Here I am facing a weird problem. As per my understanding, we use either async/await or then() function for async programming.
Here I have a db.query() method which is conducting some SQL queries to fetch data from the DB. After this function fetches the data, we do some further processing in the .then() function. However, in this approach, I was facing some issues. From where I am calling this getExpensesByFundId(int fundId)function, it doesn't seem to fetch the data properly. It's supposed to return Future> object which will be then converted to List when the data is available. But when I call it doesn't work.
However, I just did some experimentation with it and added "await" keyword in front of the db.query() function and somehow it just started to work fine. Can you explain why adding the await keyword is solving this issue? I thought when using .then() function, we don't need to use the await keyword.
Here are my codes:
Future<List<Expense>> getExpensesByFundId(int fundId) async {
Database db = await database;
List<Expense> expenseList = List();
// The await in the below line is what I'm talking about
await db.query(expTable,where: '$expTable.$expFundId = $fundId')
.then((List<Map<String,dynamic>> expList){
expList.forEach((Map<String, dynamic> expMap){
expenseList.add(Expense.fromMap(expMap));
});
});
return expenseList;
}
In simple words:
await is meant to interrupt the process flow until the async method has finished.
then however does not interrupt the process flow (meaning the next instructions will be executed) but enables you to run code when the async method is finished.
In your example, you cannot achieve what you want when you use then because the code is not 'waiting' and the return statement is processed and thus returns an empty list.
When you add the await, you explicitly say: 'don't go further until my Future method is completed (namely the then part).
You could write your code as follows to achieve the same result using only await:
Future<List<Expense>> getExpensesByFundId(int fundId) async {
Database db = await database;
List<Expense> expenseList = List();
List<Map<String,dynamic>> expList = await db.query(expTable,where: '$expTable.$expFundId = $fundId');
expList.forEach((Map<String, dynamic> expMap) {
expenseList.add(Expense.fromMap(expMap));
});
return expenseList;
}
You could also choose to use only the then part, but you need to ensure that you call getExpensesByFundId properly afterwards:
Future<List<Expense>> getExpensesByFundId(int fundId) async {
Database db = await database;
List<Expense> expenseList = List();
return db.query(expTable,where: '$expTable.$expFundId = $fundId')
.then((List<Map<String,dynamic>> expList){
expList.forEach((Map<String, dynamic> expMap){
expenseList.add(Expense.fromMap(expMap));
});
});
}
// call either with an await
List<Expense> list = await getExpensesByFundId(1);
// or with a then (knowing that this will not interrupt the process flow and process the next instruction
getExpensesByFundId(1).then((List<Expense> l) { /*...*/ });
Adding to the above answers.
Flutter Application is said to be a step by step execution of code, but it's not like that.
There are a lot of events going to be triggered in the lifecycle of applications like Click Event, Timers, and all. There must be some code that should be running in the background thread.
How background work execute:
So there are two Queues
Microtask Queue
Event Queue
Microtask Queue runs the code which not supposed to be run by any event(click, timer, etc). It can contain both sync and async work.
Event Queue runs when any external click event occurs in the application like Click event, then that block execution done inside the event loop.
The below diagram will explain in detail how execution will proceed.
Note: At any given point of application development Microtask queue will run then only Event Queue will be able to run.
When making class use async for using await its simple logic to make a wait state in your function until your data is retrieve to show.
Example: 1) Its like when you follow click button 2) Data first store in database than Future function use to retrieve data 3) Move that data into variable and than show in screen 4) Variable show like increment in your following/profile.
And then is use one by one step of code, store data in variable and then move to next.
Example: If I click in follow button until data store in variable it continuously retrieve some data to store and not allow next function to run, and if one task is complete than move to another.
Same as your question i was also doing experiment in social media flutter app and this is my understanding. I hope this would help.
A Flutter question from an answer from your answer.
await is meant to interrupt the process flow until the async method has finished. then however does not interrupt the process flow but enables you to run code when the async method is finished. So, I am asking diff. between top down & bottom down process in programming.

Unity3d Parse FindAsync method freezes UI

I'm running a simple Parse FindAsync method as show below (on Unity3d):
Task queryTask = query.FindAsync();
Debug.Log("Start");
Thread.Sleep(5000);
Debug.Log("Middle");
while (!queryTask.IsCompleted) {
Debug.Log("Waiting");
Thread.Sleep(1);
}
Debug.Log("Finished");
I'm running this method on a separate thread and I put a load circle on UI. My load freezes (+- 1 second) somewhere in the middle of the Thread.sleep method. It's look like when findAsync finishes the process it freezes the UI until it complete their job. Is there anything I could do?
Ps: This works perfectly on editor, the problem is on Android devices.
Ps2: I'm running parse 1.4.1
Ps3: I already tried the continueWith method, but the same problem happens.
IEnumerator RunSomeLongLastingTask () {
Task queryTask = query.FindAsync();
Debug.Log("Start");
//Thread.Sleep(5000); //Replace with below call
yield WaitForSeconds(5); //Try this
Debug.Log("Middle");
while (!queryTask.IsCompleted) {
Debug.Log("Waiting");
//Thread.Sleep(1);
yield WaitForSeconds(0.001f);
}
Debug.Log("Finished");
}
To call this function, use:
StartCoroutine(RunSomeLongLastingTask());
Making the thread sleep might not be a good idea, mainly because the number of threads available is different on each device.
Unity as a built-in scheduler that uses coroutines, so it is better to use it.
IEnumerator RunSomeLongLastingTask()
{
Task queryTask = query.FindAsync();
while (!queryTask.IsCompleted)
{
Debug.Log("Waiting"); // consider removing this log because it also impact performance
yield return null; // wait until next frame
}
}
Now, one possible issue is if your task take too much CPU, then the UI will still not be responsive. If possible, try to give a lower priority to this task.

Yield return in AssetBundle.CreateFromMemory

As documentation says IEnumerator methods are executed like thread, but I'm confused why
AssetBundleCreateRequest assetBundleCreateRequest = AssetBundle.CreateFromMemory(ByteArray);
yield return assetBundleCreateRequest;
freezes my game for 2 seconds. Can anybody explain?
Well it freezes for 2 seconds because that is what you are actually requesting with your yield return assetBundleCreateRequest
Asynchronous operation coroutine.
You can yield until asynchronous operation continues, or manually check whether it's done (isDone) or progress (progress). AsyncOperation
So right now you are requesting your coroutine to wait till your assetbundlecreaterequest is done.
For manually checking wheter the function is done, without having to freeze your application would be using the isdone or progress command instead
If you need further clarification feel free to comment.
Edit
Sample of using isdone
AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData);
while (!acr.isDone)
{
yield;
}
AssetBundle bundle = acr.assetBundle;

How to wait for RPCs from another presenter?

Im using gwt-platform and I have 2 Presenters ( MainpagePresenter and SecondpagePresenter). MainpagePresenter is my DefaultPlace.
So, onModuleLoad I am starting to load data from the server part with rpc and saving my data into the client cache. I implemented a PopupPanel to show a loading screen like this:
PopupPanel loadingPanel = new PopupPanel(false, true);
this.loadingPanel.add(new Label("loading..."));
this.loadingPanel.center();
this.loadingPanel.show();
So the user can't click on anything before everything is loaded sucessfully.
The Panel will be hidden when onSucess() from the rpc is called.
My SecondpagePresenter gets the saved data from the cache onReset().
#Override
protected void onReset()
{
super.onReset();
this.data = (Data) this.cache.get("Data");
}
Everything works fine, but when I am browsing the second page and do a browser refresh, the code of SecondpagePresenter will still be called before my data is received.
The only solution I found so far is to implement a while loop like this:
while(cache.get("data") != null)
{
Window.alert("loading");
}
This prevents the code to continue but the user has to click on an "OK"-Button.
So my questions is: Is there a way to block the code from SecondpagePresenter to get called before the data from my MainpagePresenter is loaded successfully?