How to save my state in Windows Store App? - c#

I have a little problem with saving my state to localsettings. Everything is ok except the situation when someone close my application using alt + f4 and open it before 10 seconds elapsed(after 10 seconds application is in state suspending and data is saved). (Technology xaml/c#)
I save my data in event OnSuspending.
I load my data in event OnLaunched like this:
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated ||
args.PreviousExecutionState == ApplicationExecutionState.ClosedByUser)
{
// save data
}
How to handle this situation ? I know i can save my state every time it is changed but i think it is not good idea in my application.
Thanks for help !

When you close and launch your application before 10 seconds elapsed another instance of it is created and the previous one does not run OnSuspending event (it is strange because it means that asynchronous operations like this event can end or never start without warning us). I think that this is annoying but why would your user do something like that? Most of the times the user "restart" your application because it crashed or he is stuck and can't go back to the main page. You should try to prevent those scenarios and such think rarely will happen.
However, this can also happen because the user forgot to do something and want to start the app again. To prevent lost user data I save the most important data whenever I get the chance and save the rest only OnSuspending method. You need to think about what data will upset your users when lost.
I think Microsoft should get a better way of saving application state. I searched a lot about this problem and didn't found an explanation so for now I will continue to do what I said above. I hope this question you made can help and clarify me about this, in my opinion, strange case.

onLaunched :
CoreWindow.GetForCurrentThread().Activated += App_Activated;
and event:
void App_Activated(CoreWindow sender, WindowActivatedEventArgs args)
{
if (args.WindowActivationState == CoreWindowActivationState.Deactivated)
{
//save Data
}
}
When you load data, remove:
if (args.PreviousExecutionState == ApplicationExecutionState.Terminated || args.PreviousExecutionState == ApplicationExecutionState.ClosedByUser)`.
It works !

Related

INotifyPropertyChanged Resubscribe not working, only the first time subscription working

I developing a Xamarin application, and I communicating an external custom device. My problem is very strange, firstly the application starting, and connecting automatically to device, so everything is fine. When i suddenly remove the battery from the external device, the bluetooth connection is broken, and it's working fine to, but when I turn on the external device again, my Xamarin application connecting to it very well well, but the subscriptions not working anymore.
I debugged it, but not calling anymore. I think the unsubscribe/subscribe process is wrong.
...
if (ble.GetConnectionStatus())
{
Device.BeginInvokeOnMainThread(() =>
{
...
ble.Adapter.DeviceConnectionLost -= Adapter_DeviceConnectionLost;
ble.Adapter.DeviceConnectionLost += Adapter_DeviceConnectionLost;
ble.PropertyChanged -= Ble_PropertyChanged;
ble.PropertyChanged += Ble_PropertyChanged;
data.PropertyChanged -= data_PropertyChanged;
data.PropertyChanged += data_PropertyChanged;
...
});
...
So it's so strange, because first time this working, when starting the app, but when I call it after reconnect that same subscription not working. So if its wrong, then why working this at very first time?
I have no error, just not fire the functions again after resubscribe.
So as you see, I need to "refresh" the subscription. Is there another way to solve this problem?
If that "button to recreate everything" works, then I see two alternatives.
Option 1:
Have such a button, so that user can manually "fix" the situation.
PRO: Gives the user a solution that is guaranteed to work.
CON: Requires user intervention.
Option 2:
Have a periodic timer, that decides whether/when to forcibly "fix" the situation.
PRO: Automatically recovers.
CON: Risks losing data, if forces a recovery at the same time data is arriving.
In pseudo-code, option 2 might be something like this:
// pseudo-code
static Timer timer = ..start a timer that has an event every 10 seconds.
OnTimerElapsed:
if (!eventSeenRecently)
ForceReset();
eventSeenRecently = false;
..whereever you receive data..
if (..has data..)
eventSeenRecently = true;
The concept is that you keep track of whether data continues to be received. If the device stops sending you information (but you believe it should be), then you "ForceReset" - whatever is needed to get everything going again.
DeviceConnectionLost should also set some flag, that you use to ForceReset when the device "comes back".
// pseudo-code
DeviceConnectionLost:
resetNeeded = true;
OnTimerElapsed:
if (resetNeeded && ..test that device is available again..) {
ForceReset();
resetNeeded = false;
}
Perhaps this custom device has some option or info that can help.
For example, there might be a way to query some id or other info, so you can discover that the device is now "different", in a way that requires the reset. Then the timer does that query, and uses that info to decide to reset.

C# Updating log textbox while running

I have spent the past few days working on bot for an MMO. It runs in one big loop, with 1-2 other smaller loops inside. So far its going great. When its running it is set to update a richtextbox with what it is currently doing, just so I can easily troubleshoot later.
My problem is while its active and looping it does not auto update the textbox until it has finished everything it is doing. Which is hard when its set in an infinite loop. I would like to be able to run the bot with the main program window on the other monitor giving me updates as it goes along.
The whole program seems to freeze up and I cant interact with it at all while running. This also causes problems when I want it to stop. The only way I have of stopping it at the minute is to click Stop in visual studio.
I have tried searching around, but I have no idea what to search for. I hope I explained it well enough.
Thanks in advance.
This would be a nice read :
http://www.beingdeveloper.com/use-dispatcher-in-wpf-to-build-responsive-applications/
To summaries
You can send in a delegate fx, which is responsible for a formatter or writter. In you implemetation it would be the one which does AppendText. and make sure the Richtextbox.AppendText is within Dispatcher.Invoke()
Code Sample
class BotRand
{
//Write Event is delegate
public execute(WriteEvent writeFx)
{
//Crawl
writeFx("message");
}
}
class MainWindow : Window
{
void WriteFunc(object message, EventArgs outline)
{
Dispatcher.Invoke(new Action(() => richText.AppendText(message));
}
}
This should help you start your search more effectively.
Thanks,

FormClosing shutdown event doesn't write to file

I have a backup power supply for my computer which is attached inline with it and the wall. When I pull the power cord from the wall, I have 2-5 minutes before the backup supply shuts down the computer. It is during this time that I want to write data to a file with the code below:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason.Equals(CloseReason.WindowsShutDown))
{
writeContents("Interrupted");
sendMessage("PWR - The Spring Test Machine has stopped");
return;
}
if (e.CloseReason.Equals(CloseReason.UserClosing))
{
if (MessageBox.Show("You are closing this application.\n\nAre you sure you wish to exit ?", "Warning: Not Submitted", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Stop) == DialogResult.Yes)
{
writeContents("Interrupted");
return;
}
else
e.Cancel = true;
}
}
The problem is that it didn't work. I don't think the the closing event ever got called. Any ideas would greatly be appreciated. Thank you.
From here http://www.daniweb.com/software-development/csharp/threads/253249/application-exit-does-not-trigger-the-formclosing
when you use taskmanager to "kill" the appliction, it doesn't fire any
events, It simply stops the execution, This is how you close an
application that has frozen. if you waited for it to handle any
events, then it would still be frozen.
as for when you restart the computer or shutdown, the event will be
called only if there is enough time, they system tells all
applications it is shutting down and only gives them a short amount of
time to handle business before it kills them. Windows 7 will show a
dialog telling you which applications are still busy and ask you if
you want to kill them and shutdown, or cancel. But as for XP, it just
kills them after X amount of seconds.
That's pretty much how I would have imagined the behavior of FormClosing... Would Application.ApplicationExit Event be a better event to listen for?
Here is some usful info about Properties of FormClosing event:
Bug in FormClosingEventArgs.CloseReason?
And you can try using switch statement, like here:
Detect reason for form closing
Not sure if it works cuase i need to check it first and im not infront of my machine now .. but have you also tried the other elements of the CloseReason enum ?
try TaskManagerClosing .
In any case try first to throw a message( messagebox ) to see if you actually have the correct CloseReason you want and also don't forget to use the e.Cancel = true if you dont want the pc to close everytime you check it .
After that check if the method you have for writting to the file is ok .
maybe this will help also
Prompt user to save when closing app

C#: Periodically update GUI based on backgroundtask

I have a GUI that is for all intents and purposes really basic. A listview, an html form, and that's really it.
I want the user to have the following behavioral ability:
1 - Click a checkbox that says "Real-time". When clicked, a background thread will run once every 10 seconds.
2 - If there is a new file created (this is easy, to observe a new file) I want an alert displayed in my main gui. Where it is displayed for now is arbitrary (in a label, for example).
The main issue is I cannot figure out how to do this in a multi-threaded example. My goal is exactly in line with multithreading: do tasks 1 and 2, without locking task 1. Meaning, while the update check is running, the user can interact with the GUI as if nothing was going on in the background.
If you need more details to better answer this please let me know.
Thanks!
Here are a couple sites I found useful for implementing a background worker when I needed to perform database operations while still allowing the GUI to be responsive:
http://msdn.microsoft.com/en-us/library/zw97wx20.aspx
http://www.codeproject.com/KB/cs/AsynchronousCodeBlocks.aspx
Use events from the thread to tell the UI that something's changed:
// Just detected that that a new file has been created
if (this.FileCreated_Event != null)
{
this.FileCreate_Event(this, new FileEventArgs(newFileName));
}
where FileCreated_Event and FileEventArgs are declared appropriately.
Then in the UI when you receive the event you have the following:
this.fileChecker.FileCreated_Event += this.FileCreated_Event;
and:
private void FileCreated_Event(object sender, TrackStatusEventArgs e)
{
if ((sender as Control).InvokeRequired)
{
(sender as Control).Invoke(action);
}
else
{
action();
}
}
where action is the thing you want to do.
Try this tutorial. At the end I'm sure you'll be able to use threads. You must be careful though, because you'll have to manage those threads which can be a daunting task. I've never met a programmer who liked to debug multiple threads...

Process.CloseMainWindow() not working

I start the Windows On-Screen-Keyboard like that:
s_onScreenKeyboard = new Process();
s_onScreenKeyboard.StartInfo = new ProcessStartInfo("osk.exe");
s_onScreenKeyboard.EnableRaisingEvents = true;
s_onScreenKeyboard.Exited += new EventHandler(s_onScreenKeyboard_Exited);
s_onScreenKeyboard.Start();
This works fine, but when I try to stop it using the following code, it does not work, i.e. the OSK keeps running and the method returns false:
s_onScreenKeyboard.CloseMainWindow();
if (!s_onScreenKeyboard.HasExited)
{
if (!s_onScreenKeyboard.WaitForExit(1000))
{
s_onScreenKeyboard.Close();
//s_onScreenKeyboard.Kill();
}
}
When uncommenting s_onScreenKeyboard.Kill(); it is closed, but the problem is that osk.exe obviously uses another process called "msswchx.exe" which is not closed if I simply kill the OSK process. This way, I would end up with hundreds of these processes which is not what I want.
Another strange thing is that the CloseMainWindow() call worked at some time, but then it suddenly did not work anymore, and I do not remember what has changed.
Any ideas?
EDIT: I have found a solution myself. Please see my answer for details.
Background:
I am implementing an On-Screen-Keyboard for my application because it should work with a touchscreen. It is important that the keyboard layout matches the layout which is configured in Windows since the application will be shipped to many different countries. Therefore, instead of implementing a custom keyboard control with approx. 537 keyboard layouts (exaggerating a little here...), I wanted to utilize the Windows built-in On-Screen-Keyboard which adapts to the selected keyboard layout automatically, saving a lot of work for me.
I have found the/a solution myself:
When I successfully retrieve the MainWindowHandle after the process has been started, the call to CloseMainWindow() is also successful later on. I do not understand the reason for this, but the important thing is: it works!
BTW, for others having the same problem: The MainWindowHandle is not available immediately after starting the process. Obviously, it takes some milliseconds until the MainWindow is started which is why I use the following code to retrieve the handle:
DateTime start = DateTime.Now;
IntPtr handle = IntPtr.Zero;
while (handle == IntPtr.Zero && DateTime.Now - start <= TimeSpan.FromSeconds(2))
{
try
{
// sleep a while to allow the MainWindow to open...
System.Threading.Thread.Sleep(50);
handle = s_onScreenKeyboard.MainWindowHandle;
}
catch (Exception) { }
}
In this code I continuously get the MainWindowHandle every ~50ms as long as it is still equal to IntPtr.Zero. If the handle could not be retrieved after 2 seconds, I quit the loop to avoid an endless loop in case of error.
You need to wait untill the process finishes initialization, run
Process.WaitForInputIdle Method in order to do that.

Categories