Hi I have a ActiveX like this:
class CMyActiveX :
public CComObjectRootEx...
...
{
HRESULT FinalContruct(){return S_OK;}
void Start()
{
// a new thread is created here for some task
}
void FinalRelease()
{
// if the thread is alive kill it
}
}
However when browser is closed the method FinalRelease is not called. So the thread keeps alive and a crash is encountered at the exit.
Any idea on this? Thank you!
I found that my control::SetClientSite(NULL) was reliably called by IE when closing or leaving the page, so I do my crucial shutdown stuff there.
It's an override of a method in IOleObjectImpl.
HRESULT CControl::SetClientSite(IOleClientSite *pClientSite)
{
if (!pClientSite) {
// Means IE is closing or about to, or at least
// that we've lost our place in the sun...
do shutdown stuff
}
IOleObjectImpl::SetClientSite(pClientSite);
if (pClientSite) {
....
MSDN - IOleObject::SetClientSite method
Related
The iOS ATT Alert needs to be shown on startup before an app starts, so the remaining app code needs to be run in the completion handler (eg initialising advert code and starting the main game).
However, this crashes because the completion handler callback is not on the main thread (after the alert is actually shown and Allow or Ask App Not to Track is selected).
In iOS (Xamarin C# code):
public override void OnActivated(UIApplication application) // RequestTrackingAuthorization must be called when app is Active
{
if (!this.shownAlert)
{
this.shownAlert=true;
Debug.WriteLine("1) ThreadId={0}", Environment.CurrentManagedThreadId); // ThreadId=1
ATTrackingManager.RequestTrackingAuthorization(delegate (ATTrackingManagerAuthorizationStatus trackingManagerAuthorizationStatus)
{
Debug.WriteLine("2) ThreadId={0}", Environment.CurrentManagedThreadId); // ThreadId=7
});
}
}
Prints:
1) ThreadId=1
2) ThreadId=7
And the similarly in Unity:
Debug.WriteLine("1) ThreadId={0}", Environment.CurrentManagedThreadId); // ThreadId=1
ATTrackingStatusBinding.RequestAuthorizationTracking(delegate (int status)
{
Debug.WriteLine("2) ThreadId={0}", Environment.CurrentManagedThreadId); // ThreadId=4
});
This seems like a bug to me. So how do all the apps and games out there get this to work? Somehow switch to the main thread in the callback? I don’t see any examples of this.
Here's my viewDidLoad method :
func viewDidLoad() {
// Stuff here
Task { #MainActor in
doSomeWorkOnMainThread1()
doSomeWorkOnMainThread2()
await doSomeBackgroundWork()
doSomeWorkOnMainThread3()
doSomeWorkOnMainThread4()
}
}
And here's my method that should execute work on a background thread :
func doSomeBackgroundWork() async {
// can add some code here
// long image processing task
assert(!Thread.isMainThread)
// can add some code here
}
Is it possible to execute doSomeBackgroundWork on a background thread (without using GCD), and wait for it before going back to the main thread ?
You are looking for Task.sleep. Note that it is in nanoseconds which is Really Weird, so I have written an extension to switch to seconds; to get it, you must use a Double, not an Int:
extension Task where Success == Never, Failure == Never {
static func sleep(_ seconds:Double) async {
await self.sleep(UInt64(seconds * 1_000_000_000))
}
static func sleepThrowing(_ seconds:Double) async throws {
try await self.sleep(nanoseconds: UInt64(seconds * 1_000_000_000))
}
}
The way to guarantee that a piece of work will be done on a background thread is to give that work to an Actor. That is what an Actor is for (in part).
So for example if an Actor has a method doSleep that calls Task.sleep, then if you instantiate that actor and call that method from your Task, it will sleep on a background thread.
This solution is working, but it's not perfect I guess :
func doSomeBackgroundWork() async {
await Task {
// long image processing task
assert(!Thread.isMainThread)
}.result
}
I am using a ListField Control to display data returned from xml webservice. I want to refresh the ListField or the screen every minute to update the ListField with new records or data.
I tried using the code below but it is not working properly (It is hanging).
public MyApp() {
// Push a screen onto the UI stack for rendering.
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new MyScreen());
}
},5000,true);
}
ResponseHandler handler = new ResponseHandler();
ListField listUsers = new ListField(handler.getItem().size());
public MyScreen() {
setTitle("yQAforum");
//Fetch the xml from the web service
String wsReturnString = GlobalV.Fetch_Webservice("myDs");
//Parse returned xml
SAXParserImpl saxparser = new SAXParserImpl();
ByteArrayInputStream stream = new ByteArrayInputStream(wsReturnString.getBytes());
try {
saxparser.parse( stream, handler );
}
catch ( Exception e ) {
response.setText( "Unable to parse response.");
}
//Return vector sze from the handler class
listUsers.setSize(handler.getItem().size());
listUsers.setCallback(this);
listUsers.setEmptyString("No Users found", 0);
add(listUsers);
}
You are attempting to fetch data from your webservice on the UI thread. That's almost always the wrong thing to do.
The UI thread (also known as the main thread) is responsible for drawing the UI, and tracking user actions, like touches, or navigation via a trackpad/trackball. If the UI thread is blocked waiting for a remote web server to respond, it cannot service the UI.
There's a couple changes you should make:
public MyApp() {
// Push a screen onto the UI stack for rendering.
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new MyScreen());
}
},5000,true);
}
should be changed to
public MyApp() {
// Push a screen onto the UI stack for rendering.
pushScreen(new MyScreen());
}
The MyApp() constructor will already be called on the UI thread, so there is no need to use invokeLater() to perform the pushScreen() call on the UI thread. It already will be called on the UI thread, if run from within the MyApp constructor. Also, the 5000 msec delay isn't really helpful. This will just delay the startup of your app by 5 seconds, which users will hate.
If you are trying to implement a splash screen, or something similar, when the app starts up, please search stack overflow for "BlackBerry splash screen", and I'm sure you'll find results.
Now, once your MyScreen class is created, you should take care not to fetch web service results from the UI thread. The MyScreen constructor will be run on the UI thread. If you want, you can initiate a web service request on a background thread, once the screen is shown. One way to do that is to use onUiEngineAttached():
protected void onUiEngineAttached(boolean attached) {
if (attached) {
// TODO: you might want to show some sort of animated
// progress UI here, so the user knows you are fetching data
Timer timer = new Timer();
// schedule the web service task to run every minute
timer.schedule(new WebServiceTask(), 0, 60*1000);
}
}
public MyScreen() {
setTitle("yQAforum");
listUsers.setEmptyString("No Users found", 0);
listUsers.setCallback(this);
add(listUsers);
}
private class WebServiceTask extends TimerTask {
public void run() {
//Fetch the xml from the web service
String wsReturnString = GlobalV.Fetch_Webservice("myDs");
//Parse returned xml
SAXParserImpl saxparser = new SAXParserImpl();
ByteArrayInputStream stream = new ByteArrayInputStream(wsReturnString.getBytes());
try {
saxparser.parse( stream, handler );
}
catch ( Exception e ) {
response.setText( "Unable to parse response.");
}
// now, update the UI back on the UI thread:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// TODO: record the currently selected, or focused, row
//Return vector sze from the handler class
listUsers.setSize(handler.getItem().size());
// Note: if you don't see the list content update, you might need to call
// listUsers.invalidate();
// here to force a refresh. I can't remember if calling setSize() is enough.
// TODO: set the previously selected, or focused, row
}
});
}
}
You'll need to add some error handling, in case the web service doesn't respond, or takes longer than a minute (you wouldn't want to be making a new request, if the last one hadn't finished).
But, this should get you started.
Note: once you fix the problem with running network code on the UI thread, you may still find that your code doesn't work. There could be problems fetching the web service data. You'll have to debug that. I am only showing you one problem with the code posted. If you still have problems with the web service fetch, post another question (with the UI thread problem fixed). Thanks.
I have a Blackberry application which, when run in some emulators with touch support (ex: 9500, 9520, 9530, 9550), terminates with:
"Application is not responding; process XPTO terminated"
Using logs, I found out that it seems like the application is stopping in a class where I asynchronously make HTTP requests: something like:
public class LoadingFullScreen extends FullScreen implements Runnable {
private Thread actionThread = null;
protected void onDisplay() {
actionThread = new Thread(this);
actionThread.start();
}
protected void onUndisplay() {
if(actionThread != null && actionThread.isAlive()) {
actionThread.interrupt();
}
}
public void run() {
//make http requests - this is done successfully
synchronized(Application.getEventLock()) {
Screen active = UiApplication.getUiApplication().getActiveScreen();
if (active instanceof LoadingFullScreen) {
Logger.debug("LoadingFullScreen popping screen"); //this appears in logs
UiApplication.getUiApplication().popScreen(active);
Logger.debug("LoadingFullScreen screen popped"); //this never appears in logs
}
}
}
}
I launch this screen with UiApplication.getUiApplication().pushModalScreen(new LoadingFullScreen())
In the logs I can see:
[0.0] Wed Jul 27 17:53:06 GMT 2011 - DEBUG: LoadingFullScreen popping screen
[0.0] JVM: bklt[1] #163148: JBSC on=0
[0.0] JVM: bklt[1] #163148: SC 0
[0.0] JVM: bklt[1]: setTimeout 30
[0.0] Application XPTO(212) is not responding; process terminated
It seems like UiApplication.getUiApplication().popScreen() is blocking the application, and so the OS kills the application, but why?
EDIT:
I have also tried using
UiApplication.getUiApplication().invokeLater(new Runnable() {...} };
instead of synchronized(Application.getEventLock()) {...} but I have the exact same result
EDIT 2:
I have also tried active.close() instead of UiApplication.getUiApplication().popScreen(active); but I have the exact same result
EDIT 3:
Using javaloader I got this kind of stacktrace from the emulator:
guid:0x9C3CD62E3320B498 time: Thu Jul 28 15:02:50 2011 severity:0 type:3 app:Java Exception data:
ForcedStackTraceException
net_rim_services_impl(4) 27 2 0x1030B000
net_rim_os-3(4BEF0320)
HttpConnectionManager$CleanupThread
run
0x3B09
guid:0x9C3CD62E3320B498 time: Thu Jul 28 15:02:50 2011 severity:0 type:3 app:Java Exception data:
ForcedStackTraceException
XPTO(247) 60 4 0x124A0400
net_rim_cldc-16(4BEEF8A5)
TextField
getFocusRect
0x2A61
net_rim_cldc-12(4BEEF8A5)
Manager
getFocusRect
0x717
net_rim_cldc-12(4BEEF8A5)
Manager
getFocusRect
0x717
net_rim_cldc-12(4BEEF8A5)
Screen
getFocusRect
0x9AF2
net_rim_cldc-12(4BEEF8A5)
Screen
callOnExposed
0x9D16
net_rim_cldc-13(4BEEF8A5)
UiEngineImpl
<private>
0x9007
net_rim_cldc-13(4BEEF8A5)
UiEngineImpl
removeScreen
0x7D08
net_rim_cldc-12(4BEEF8A5)
Screen
close
0x6B66
XPTO-8(4E316B06)
LoadingFullScreen$1
run
0x34D5
net_rim_cldc-8(4BEEF8A5)
Application
dispatchInvokeLater
0x1A87
net_rim_cldc-8(4BEEF8A5)
Application
<private>
0x2809
net_rim_cldc-8(4BEEF8A5)
Application
processNextMessage
0x1AEF
net_rim_cldc-9(4BEEF8A5)
ModalEventThread
run
0xBE4F
guid:0x9C3CD62E3320B498 time: Thu Jul 28 15:02:50 2011 severity:0 type:3 app:Java Exception data:
ForcedStackTraceException
XPTO(247) 30 2 0x139DA800
net_rim_cldc(4BEEF8A5)
Object
wait
0x9922
net_rim_cldc-8(4BEEF8A5)
Application
startModalEventThread
0x1EB8
net_rim_cldc-13(4BEEF8A5)
UiEngineImpl
addScreenModal
0x83F4
net_rim_cldc-13(4BEEF8A5)
UiEngineImpl
pushModalScreen
0x674E
net_rim_cldc-13(4BEEF8A5)
UiApplication
pushModalScreen
0x62B0
XPTO-8(4E316B06)
MyBaseScreen
<private>
0x3AA6
XPTO-8(4E316B06)
MyBaseScreen
openTheModalScreenFunction
0x382C
XPTO-8(4E316B06)
MyBaseScreen$4
fieldChanged
0x4271
net_rim_cldc-11(4BEEF8A5)
Field
fieldChangeNotify
0x160B
net_rim_cldc-16(4BEEF8A5)
TextField
replace
0x7A5
net_rim_cldc-16(4BEEF8A5)
TextField
inputMethodTextChanged
0x24E1
net_rim_cldc-15(4BEEF8A5)
PasswordEditField
inputMethodTextChanged
0x4F26
net_rim_cldc-27(4BEEF8A5)
IMContext
dispatchInputMethodEvent
0x1E00
net_rim_tid-4(4BEEF8E1)
SLInputMethod
sendComposedText
0x5CA1
net_rim_tid-4(4BEEF8E1)
SLInputMethod
sendComposedText
0x5BD1
net_rim_tid_fastEuropean(4BEF034C)
FastEuropeanInputMethod
sendComposedText
0x48E1
net_rim_tid_fastEuropean(4BEF034C)
FastEuropeanInputMethod
dispatchConversionEvent
0x43E3
net_rim_tid-4(4BEEF8E1)
SLInputMethod
dispatchKeyEvent
0x5309
net_rim_tid-4(4BEEF8E1)
SLInputMethod
dispatchEvent
0x63CA
net_rim_tid_fastEuropean(4BEF034C)
FastEuropeanInputMethod
dispatchEvent
0x426E
net_rim_cldc-27(4BEEF8A5)
InputContext
dispatchEvent
0x3E15
net_rim_cldc-27(4BEEF8A5)
IMContext
dispatchEvent
0x21DE
net_rim_cldc-11(4BEEF8A5)
Field
dispatchEvent
0x3739
net_rim_cldc-16(4BEEF8A5)
TextField
dispatchEvent
0x30F6
net_rim_cldc-27(4BEEF8A5)
EventHandler
<private>
0x1460
net_rim_cldc-27(4BEEF8A5)
EventHandler
processKeyEvent
0x1A79
net_rim_cldc-16(4BEEF8A5)
TextField
processKeyEvent
0x37F6
net_r
EDIT 4:
I have tried to move the run() method in LoadingFullScreen to a new Runnable class, as I was told that having LoadingFullScreen implement Runnable could cause problems when that class is shown as a modal screen.
However, I had no luck and I still have the same problem.
Any ideas?
EDIT 5:
Solved here: BlackBerry: "Application is not responding; process terminated" because of UiApplication.getUiApplication().popScreen()?
I remember that once I had almost same kind of problem. Whenever I tried to pop screen by acquring lock of Event thread, the app would crash. SO instead of getting hold(lock) of Event thread, try synchronizing on Event thread using invokeLater().
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
}
});
As none of the answers solve the problem, I am posting here the solution I reached with help from other forum (http://supportforums.blackberry.com/t5/Java-Development/Application-is-not-responding-process-terminated-because-of/m-p/1234573#M168285)
I didn't find it relevant, but it seems that the way I was calling LoadingFullScreen matters:
public void fieldChanged(Field field, int context) {
LoadingFullScreen loading = new LoadingFullScreen();
System.out.println("calling pushModalScreen"); //this was showing up in logs
UiApplication.getUiApplication().pushModalScreen(loading);
System.out.println("pushModalScreen done"); //this wasn't showing up in logs
}
It turns out the emulators/devices I mentioned have support for 'SureType'.
"That means they do some off things when you press a key. Typically, they will attempt to display a 'choice' for the user, becuase each key has two options. becuase you are doing a pushModal in the FieldChanged method, you are blocking this. And this I think is what it is getting upset about."
So the solution was to change the way this instead:
public void fieldChanged(Field field, int context) {
if ( context != FieldChangeListener.PROGRAMMATIC ) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
LoadingFullScreen loading = new LoadingFullScreen();
UiApplication.getUiApplication().pushModalScreen(loading);
}
}
}
}
Assuming smth is wrong (assuming there's a RIM bug) with UiApplication.getUiApplication().popScreen() here is just an idea to try:
Instead of UiApplication.getUiApplication().popScreen(active); try to call active.close().
i believe this is because ui thread and ur thread created are not communicating properly. you can use this following code.
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
}
});
I was having similar strange issues with a popup screen I implemented. It turned out that I had 2 different methods trying to pop the screen at the same time. This led to the error.
I ended up creating a static helper method that I now use to close my screens, which checks if the screen is actually displayed before closing it.
Posted here in case it helps someone:
/**
* Convenience method to request a screen to close & pop it from the display
* stack. This method handles the UI threading issues.
*
* #param screen
* {#link Screen} to be closed.
*/
public static void closeScreen(final Screen screen)
{
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
if (screen.isDisplayed())
{
screen.close();
}
}
});
}
I have experienced something similar to this. I have a callback (invoked from another thread) in which processing happens, and informs the user of the indication of processing via Status and was using code like this:
UiApplication.getUIApplication.invokeLater(new Runnable(){
public void run(){
Status.show("....");
}
});
And was getting near identical errors as the OP.
I realized then, because the callback was being executed multiple times, ALL of those Runnables were being queued up and hence "Too many threads" followed by a nice crash!
The solution:
UiApplication.getUIApplication.invokeAndWait(new Runnable(){
public void run(){
Status.show("....");
}
});
That will block until the event queue gets cleared making way for more Status showing up.
Since its on a thread, it does not matter and thus a nice compromise.
End result: No more nasty crashes and no spurious messages in the event log.
To the OP: You may have to restructure slightly how you're informing the end user on notification of processing the UI logic in order not to exhaust the threading pool.
BTW, it should be noted - this is on BB 4.5 :)
I have an app that is listening in background and when the user clicks "send" it displays a dialogue. However I need to bring my app to foreground so the user answers some questions before letting the message go. but I haven't been able to do this, this is the code in my SendListener:
SendListener sl = new SendListener(){
public boolean sendMessage(Message msg){
Dialog myDialog = new Dialog(Dialog.D_OK,
"message from within SendListener",
Dialog.OK,Bitmap.getPredefinedBitmap(Bitmap.EXCLAMATION),
Dialog.GLOBAL_STATUS)
{
//Override inHolster to prevent the Dialog from being dismissed
//when a user holsters their BlackBerry. This can
//cause a deadlock situation as the Messages
//application tries to save a draft of the message
//while the SendListener is waiting for the user to
//dismiss the Dialog.
public void inHolster()
{
}
};
//Obtain the application triggering the SendListener.
Application currentApp = Application.getApplication();
//Detect if the application is a UiApplication (has a GUI).
if( currentApp instanceof UiApplication )
{
//The sendMessage method is being triggered from
//within a UiApplication.
//Display the dialog using is show method.
myDialog.show();
App.requestForeground();
}
else
{
//The sendMessage method is being triggered from
// within an application (background application).
Ui.getUiEngine().pushGlobalScreen( myDialog, 1,
UiEngine.GLOBAL_MODAL );
}
return true;
}
};
store.addSendListener(sl);
App is an object I created above:
Application App = Application.getApplication();
I have also tried to invoke the App to foreground using its processID but so far no luck.
i have managed to achieve something similar to what you're describing but the difference is, my dialogs are displayed asynchronously, which might actually be easier... so in your case..
the first i could suggest you try is get the event lock before pushing the screen, ala:
synchronized(Application.getEventLock()){
final UiEngine ui = Ui.getUiEngine();
ui.pushGlobalScreen(theScreen, 1, UiEngine.GLOBAL_MODAL);
}
I would also just create a custom class of type MainScreen and push that instead of plain Dialog.
There, that's better (now with code formatting).
public class MYSendListener implements SendListener {
private UiApplication _myApp;
public MySendListener(UiApplication myApp) {
_myApp = myApp;
}
public boolean sendMessage(Message m) {
...
_myApp.requestForeground();
}
}
Cache your app instance inside your send listener when you construct it, and use that when sendMessage is fired.
Application.getApplication() only gets you the app of the calling thread.