notifyDestroyed() method is called by the MIDlet to notify AMS that it want to go to the Destroyed State. once this notification is received by the AMS, it will asssume that the MIDlet has already done all the resources clearing process before calling notifyDestroyed() method.
Therefore is it going to kill the MIDlet rather than calling destroyApp() method.
It seems like it is best practice to call destroyApp() before notifyDestroyed().
try {
// Call destroyApp to release resources
destroyApp(false);
// Arrange for the MIDlet to be destroyed
notifyDestroyed();
} catch (MIDletStateChangeException ex) {
// MIDlet does not want to close
}
The AMS will definitely not call destroyApp() after notifyDestroyed() has been called.
An incorrect AMS that would do this could end up in a stack overflow situation when running a correct MIDlet.
Related
How can you make a background web request and then update the UI, but have all the code that does the web requesting/parsing in a separate class so you can use it in multiple places? I thought I could use the classes methods as event handlers for a BackgroundWorker class, like
APIHelper mHelper = new APIHelper("http://example.com?foo=bar");
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork +=new DoWorkEventHandler(mHelper.GetResponse);
bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(mHelper.HandleResponse);
bw.RunWorkerAsync();
where APIHelper has the method
public void GetResponse(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker) sender;
WebRequest request = HttpWebRequest.Create(this.URL);
IAsyncResult result = (IAsyncResult)
request.BeginGetResponse(ResponseCallback, request);
}
but then I don't know how to access the worker thread from ResponseCallback and, anyway, HandleResponse gets called first (obviously). (I tried putting in result.AsyncWaitHandle.WaitOne(); but I get a NotSupportedException error.) Yet I can't work out how to make the web request call synchronously. I'm clearly trying to go about this the wrong way, but I have no idea what the right way is.
ETA:
My aim is to be able to go:
user clicks (a) button(s) (on various pages)
a "working" message is displayed on the UI thread (and then input is blocked)
in a background thread my APIHelper class makes the relevant API call, gets the response, and passes it back to the UI thread; I only seem to be able to do this by starting another thread and waiting for that to return, because there's no synchronous web requests
the UI thread updates with the returned message (and input continues as before)
I can do the first two bits, and if I have the response, I can do the last bits, but I can't work out how to do the middle bit. Hopefully that made it clearer!
It took me several tried before I found there is a Dispatcher.
During the BackgroundWorker's dowork and complete methods you can call:
this.Dispatcher.BeginInvoke(() =>
{
// UPDATE UI BITS
});
I think the Dispatcher is only available in the view. So I'm not sure if the methods can exist outside of the xaml.cs
Put whatever you want to update in your UI; when updating an ObservableCollection you must do the update of you items in the Dispatcher.BeginInvoke too
This link might be a good read too:
http://www.windowsphonegeek.com/articles/All-about-Splash-Screens-in-WP7-ndash-Creating-animated-Splash-Screen
Update to assist notes
This is just a rough idea mind you...
bw.DoWork +=new DoWorkEventHandler(DoWork);
bw.RunWorkerCompleted +=new RunWorkerCompletedEventHandler(Complete)
// At least I think the EA is DoWork....
public void DoWork(object sender, DoWorkEventArgs e)
{
mHelper.GetResponse();
this.Dispatcher.BeginInvoke(() =>
{
UIObject.Visibility Collapse.
});
// Wait and do work with response.
});
}
public void Complete(object sender, RunWorkerCompleteEventArgs e)
{
this.Dispatcher.BeginInvoke(() =>
{
UIObject.Visible ....
});
}
I'd put all this logic in a viewmodel that the viewmodel of each page inherits from.
Have the pages bind to properties on the viewmodel (such as ShowLoading, etc.) which the model updates appropriately. i.e. before making the webrequest and in the callback.
As you won't be running the viewmodel code in the UI thread you also wouldn't need to run in a separate BackgroundWorker and you'll be able to access the properties of the viewmodel without issue.
It might be useful if you use a helper class that I have developed for WebDownload purposes during WP7 development.
I'm using it in 2-3 WP7 apps and no problem so far. Give it a go to see if it helps. You can get the class from the my blog linked bellow:
http://www.manorey.net/mohblog/?p=17#content
[NOTE] When working with this class you don't need to run anything in a background worker or new thread; it handles it all asynchronously.
I have a Silverlight application that uses WCF services and also uses the Wintellect Power Threading library to ensure logic executes fully before the application continues. This is achieved by calling back to the application using delegates so it can continue after the service call has completely finished.
I wish to achieve the same thing in another part of my application but without the use of callbacks e.g. call method that uses WCF service to say load an object from the database, wait for this to return and then return the Id of the object from the original method called.
The only way I could see to do this was to carry out the call to the WCF service in a helper library which loads the object on a different thread and the original method would keep checking the helper library (using static variables) to wait for it to complete and then return it.
Is this the best way to achieve this functionality? If so here are details of my implementation which is not working correctly.
public class MyHelper
{
private static Thread _thread;
private static User _loadedObject;
public static GetUser()
{
return _loadedObject;
}
public static void LoadObject(int userId)
{
_loadedObject = null;
ParameterizedThreadStart ts = new ParameterizedThreadStart(DoWork);
_thread = new Thread(ts);
_thread.Start(userId);
}
private static void DoWork(object parameter)
{
var ae = new AsyncEnumerator();
ae.BeginExecute(DoWorkWorker(ae, Convert.ToInt32(parameter)), ae.EndExecute);
}
private static IEnumerator<Int32> DoWorkWorker(AsyncEnumerator ae, int userId)
{
// Create a service using a helper method
var service = ServiceHelper.GetService<IUserServiceAsync>();
service.BeginGetUserById(userId, ae.End(), null);
yield return 1;
_loadedObject = service.EndGetUserById(ae.DequeueAsyncResult());
_thread.Abort();
}
}
My method then is:
public int GetUser(int userId)
{
MyHelper.LoadObject(userId);
User user = MyHelper.GetUser();
while (user == null)
{
Thread.Sleep(1000);
user = MyHelper.GetUser();
}
return user.Id;
}
The call to the get the user is executed on a different thread in the helper method but never returns. Perhaps this is due to the yield and the calling method sleeping. I have checked the call to get the user is on a different thread so I think everything should be kept separate,
The whole construct you are using does not match current best practices of Silverlight. In Silverlight your data access methods (via WebServices of course) are executed asynchronously. You should not design around that, but adapt your design accordingly.
However calling services sequentially (which is different than synchonously) can be valid in some scenarios. In this blog post I have shown how to achieve this by subscribing the Completed event of the remote call and block the UI in the meantime, with which the workflow looks and feels like normal async calls.
I believe calls to the server from Silverlight apps use events that fire on the UI thread; I think that's part of the Silverlight host environment in the browser and can't be worked around. So trying to call back to the server from another thread is never going to end well. If you are waiting in program code in the UI thread, your never going to get the call result events from your WCF calls.
You can simulate a synchronous call from a non-UI thread with a callback on the UI thread, but that is probably not what you want. It's better to bite the bullet and make your program logic work with the async calls Silverlight gives you.
If you code against the Interface created for your service reference you can call the Begin and End methods 'synchronously' for each one of your service calls, we then pass in an Action<T> to execute after the End methods has completed. Take note that you have to do this from a dispatcher. This is very close to making a synchronous call as the code to run after the call is still written where the call is made, and it executes after the service call is completed. It does however involve creating wrapper methods but we also worked around that by hiding our wrappers and generating them automatically. Seems like a lot of work but isn't, and ends up being more elegant than all the event handlers etc. Let me know if you need more info on this pattern
Can somebody please explain why the event "OnNewMail" is not raised when using an STA thread in the code below? The program attempts to use the Redemption library to intercept incoming outlook mails.
class Program
{
[STAThread()] // When this line is deleted the application works
static void Main(string[] args)
{
RDOSession session = GetSession();
session.OnNewMail += Session_OnNewMail;
Console.ReadLine();
}
static void Session_OnNewMail(string EntryID)
{
Console.WriteLine("New mail received");
}
private static RDOSession GetSession()
{
var session = new RDOSession();
var application = new ApplicationClass();
session.MAPIOBJECT = application.Session.MAPIOBJECT;
return session;
}
}
COM running on an STAThread uses a message pump to raise events and call methods. When in a console application there isn't a window to pump messages for you so you need to run the pump yourself. (Several of the .NET synchronisation methods will do this for you - have a look at WaitOne etc...)
If the object is happy within a default MTA thread - you may be better off using that if you need to do this from a console application.
Instead of ReadLine - you can poll for a key and pump messages using this:
while (Console.Read() == 0)
{
Thread.CurrentThread.Join(100);
}
...but this is a hack.
Mixing COM, console apps and [STAThread] is a bit fishy and can result in other problems:
http://support.microsoft.com/default.aspx/kb/828988
When the tread is STA thread and you wait for input the library can't do anything at the same time and has no chance to fire the event when an email arrives.
The problem almost certainly has to do with message pumping.
Unless we know what type of COM object RDOSession is (STA, MTA, etc ...) we can only speculate as to what is actually going on.
My guess is that RDOSession is an MTA COM object and that somehow the event code has bound the event to an STA proxy or object. This means that part of the raising of the OnNewMail event must marshal the raise onto the STA thread. This involves window message passing. You are doing a simple ReadLine call which is a blocking call and will not process messages. Hence you won't ever get the event.
Mobile app provides the user with the option of downloading the email attachment from remote.Connecting with a remote server and downloading the content is carried out in a separate thread.A dialog is shown to the user with cancel command.Herewith I am providing the pseudo code.
new Thread(new Runnable()
public void run(){
try{
//open connection to remote server
//get data input stream
//create byte array of length attachment size
//show modeless dialog with the message "Downloading..."
for(int i=0;i<attachmentSize;i++){
//set the progress indicator of the modeless dialog based upon for iteration
//read the byte from input stream and store it in byte array
}
//open file connection outputstream and store the downloaded content as a file in mobile file system
//show dialog with the message "attachment successfully downloaded"
}
catch(IOException ioe) { }
catch(Exception ex) { }
}
).start();
Now I'm in the process of adding cancel command to the dialog with progress indicator. When the user clicks "Cancel" command in mobile, modeless dialog can be disposed by calling dispose() method. How can I abruptly stop the thread which gets the email attachments via streaming?
Please do help me to resolve this issue.
You can stop it abruptly - but it brings more trouble that it's worth.
The canonical way of doing this is to have a flag which is checked in the Runnable:
public class ClassHoldingRunnable {
private volatile boolean stopRequested = false;
public void executeAsync() {
Runnable r= new Runnable() {
public void run() {
while ( !stopRequested ) {
// do work
}
}
}
new Thread(r).start();
}
public void cancel() {
stopRequested = true;
}
}
A few notes:
it's vital for the stopRequested flag to be either volatile or to have another visibility guarantee ( synchronized, Lock, Atomic ) since it's being accessed by multiple threads;
you should check for stopRequested pretty often if it's important for the end user to have a responsive GUI;
There are several complimentary ways to interrupt a Thread that reads from a Connection.
You are probably reading the remote data by looping over a single call to InputStream.read, so you can reuse a single, relatively small, byte[] object. You can check a boolean member variable before each iteration. You don't really need to synchronize around that boolean because it is only supposed to change value once after Thread construction.
closing the Connection means that your Thread will throw a IOException when it next tries to access it. A proper JavaME implementation will not make Connection.close() block even if another Thread is reading from the Connection's InputStream.
I am not an expert on this so take my suggestion with a grain of salt, as my experience is very limited on Java threads.
You cannot stop a running thread. You can just exit it as soon as possible. So what you could do is to have, for example, a shared flag that you test periodically in the secondary thread. When the main thread sets it in response to a Cancel click, the secondary thread returns.
My experience is more in C# but this might still be applicable...
I don't think it's a good idea to find some way of just "killing a thread" any more than you would just delete an object and skip its destructor.
You could tell the thread to commit suicide via an interrupt. You can then either use the thread's interrupted flag as the indicator or, if you have a sleep/wait in there, you could catch an interrupted exception and shut down properly when this is caught (in the finally block). This should provide, more or less, what you're looking for.
A backend webapp is deployed on a Tomcat 6 servlet container. In the webapp, several monitoring threads are started. The problem is with shutdown.
How do I know that the webapp is requested to shutdown?
How should I handle this in my threads?
Currently my thread is implemented as below. When the servlet is instructed to shutdown (shutdown.sh) it does complete a clean shutdown and does not hang because of this thread -- Why?
class Updater extends Thread {
volatile boolean interrupted = false;
#Override
public void run() {
Integer lastUpdateLogId = CommonBeanFactory.getXXX()
.getLastUpdateLogRecordKey(MLConstants.SMART_DB_NAME);
List<UpdateLog> updateLogRecords;
while (!interrupted) {
boolean isConfigurationUpdateRequested = false;
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
setInterrupted(true);
}
updateLogRecords = CommonBeanFactory.getXXX()
.getLastFactsUpdateLogRecords(MLConstants.XXXX, lastUpdateLogId);
for(UpdateLog updateLog : updateLogRecords) {
if (updateLog.getTable_name().equals(MLConstants.CONFIG_RELOAD)) {
isConfigurationUpdateRequested = true;
}
lastUpdateLogId = updateLog.getObjectKey();
}
if (isConfigurationUpdateRequested) {
Configuration.getInstance().loadConfiguration();
}
}
}
public boolean getInterrupted() {
return interrupted;
}
public void setInterrupted(boolean interrupted) {
this.interrupted = interrupted;
}
}
I guess I can't reply to answers yet. Eddie's answer is not quite correct.
I found this question because I'm trying to figure out why my webapp doesn't shut down properly; I have threads that don't get killed when I run shutdown.*. In fact, it stops some threads but ultimately just sits there in some limbo state. My class is almost exactly like this one, actually.
Typing Ctrl+C in the foreground Tomcat window (on Windows) does stop everything, however using the init script that comes with Tomcat does not. Unfortunately, I haven't figured out why yet...
Edit: I figured it out. Most of my monitoring threads are started in a ServletContextListener, but when that context was "destroyed", the child threads weren't notified. I fixed it by simply keeping all child threads in a List and looping through, calling Thread.interrupt() on each within the contextDestroyed() method. It's almost the same as what Eddie said about the servlet destroy() method.
However, it's not correct that the JVM is summarily shut down when you run shutdown.{sh|bat}. It's more like that script sends a shutdown request to the Tomcat components. It's up to you to receive those shutdown messages and pass them along to your own objects.
Servlets receive a lifecycle event when instructed to shut down. You can use this event to stop your monitoring Thread. That is, when a servlet is started, its init() method is called. When it is stopped, its destroy() method is called.
Override the destroy() method in your servlet and stop the thread there.
When you call shutdown.sh the whole JVM is shut down. Because the JVM stops, all threads (no matter what their state) are forcibly stopped if still running. It's the logical equivalent of calling System.exit(0);