I'm studying right now the bluetooth Android API, and I ran into the BluetoothChat example.
http://developer.android.com/resources/samples/BluetoothChat/index.html
It contains many errors, first of all the simple fact that it uses API 11 but manifest does not force this minimum API.
Other interesting thing is the use of synchronized keyword on Activity lifecycle methods, like on onResume:
#Override
public synchronized void onResume() {
super.onResume();
if(D) Log.e(TAG, "+ ON RESUME +");
// Performing this check in onResume() covers the case in which BT was
// not enabled during onStart(), so we were paused to enable it...
// onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
if (mChatService != null) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
}
}
}
Why this keyword is used there? Is there any reasonable explanation, or simply the one who wrote the code didn't know that onResume will be called always by the same thread? Or I miss something?
Thank you in advance!
This seems to be a pretty old question, but here's what I think may be going on:
My guess is that it wants to be careful about when "dialogs" return. The BluetoothChat example uses dialogs (as well as an overlay dialog-like activity) for enabling Bluetooth, enabling discovery, and initiating pairing/connections.
I don't know this for sure but I suspect there was a bug where different threads were returning to the main Activity and caused confusion as to how to handle onResume.
What they probably should have done is synchronize a block on an object and used flags to determine the state. That way the intention, state and functionality are more clear -- and the app knows what it should do in onResume;
something like this maybe:
//class fields
private Object myLockObj = new Object();
private boolean isPausedForPairing = false;
public void onResume()
{
super.onResume();
synchronized (myLockObj)
{
if (isPausedForPairing)
{
//handle a "pairing" onResume
}
}
}
However, due to it being an example app, they may have decided to go with something more simple. Example apps don't always follow convention because the idea is to demonstrate the particular code needed for the example. Sometimes following convention might add a lot of "distracting" code. Whether or not you agree with that is up to you though.
Related
I've been having some issues with threading in monotouch. My app makes use of an external library which I've linked with and it works fine. Because of the nature of the app and the library I have to make all the calls to it on a single separate thread.These calls will generally be :
Random non deterministic caused by user
Every t miliseconds(around 20ms). Like an update function
After reading for a bit I decided to try out NSThread. I've managed to call the Update function by attaching an NSTimer to the thread's RunLoop and it's all working fine. The problem that I'm having now is calling other methods on the same thread. I read somewhere that using PerformSelector on the RunLoop adds the selector invocation to the RunLoop's queue and invokes it when available, which is basically exactly what I need. However the methods that I need to call :
Can have multiple paramteres
Have callbacks, which I need to invoke on the main thread, again with multiple parameters
For the multiple parameters problem I saw that NSInvocation can be a solution, but the life of me I can't figure out how to do it with monotouch and haven't found any relevant examples.
For the actuals calls that I need to make to the library, I tried doing a generic way in which I can call any function I choose via delegates on a particular thread, which sort of works until I'm hit with the multiple parameters and/or callbacks to the main thread again with multiple parameters. Should I maybe just register separate selectors for each (wrapped)function that I need to call from the library?
I'm not hellbent on using this approach, if there is a better way I'm open to it, it's just that after searching for other options I saw that they don't fit my case:
GCD(not even sure I have it in monotouch) spawns threads on it's own whenever necessary. I need a single specific thread to schedule my work on
NSInvocationQueue(which uses GCD internally from what I read) does the same thing.
pThreads, seem overkill and managing them will be a pain(not even sure I can use them in monotouch)
I'm not an iOS developer, the app works fine with monodroid where I had Runnables and Handlers which make life easier :) . Maybe I'm not looking at this the right way and there is a simple solution to this. Any input would be appreciated.
Thanks
UPDATE
I was thinking of doing something along these lines :
Have a simple wrapper :
class SelectorHandler : NSObject
{
public static Selector Selector = new Selector("apply");
private Action execute;
public SelectorHandler(Action ex)
{
this.execute = ex;
}
[Register("apply")]
private void Execute()
{
execute();
}
}
Extend NSThread
public class Daemon : NSThread
{
public void Schedule(Action action)
{
SelectorHandler handler = new SelectorHandler(action);
handler.PerformSelector(SelectorHandler.Selector, this, null, true);
}
}
Then, when I want to call something I can do it like this :
private Daemon daemon;
public void Call_Library_With_Callback(float param, Action<int> callback)
{
daemon.Schedule(() =>
{
int callbackResult = 0;
//Native library calls
//{
// Assign callback result
//}
daemon.InvokeOnMainThread(() =>
{
callback(callbackResult);
});
});
}
I've started developing a Leap Motion app and this is driving me nuts. Whenever I exit the application, the code responsible for cleaning up the Leap Motion controller hangs on me.
public void CleanUp()
{
_lmController.RemoveListener(_lmListener);
_lmController.Dispose();
}
I create both the controller and the listener in my Main Thread in a presenter class:
public MainViewPresenter(IMainView view, IApplicationController applicationController)
{
_view = view;
_applicationController = applicationController;
_view.Presenter = this;
_lmListener.Frame += _lmListener_Frame;
_lmController.AddListener(_lmListener);
}
The Cleanup() method is also a presenter method called on the view's FormClosing event. The weird thing is that it works perfectly fine when I call it from _listener_Frame(), which runs on a separate, Leap Motion-created no-name thread!
_lmListener_Frame() itself resides in the presenter. It just gets data from _lmController, creates a view model and sends it to the view, which in turn uses Invoke to update the display data.
I've tried calling the CleanUp stuff in Dispose() (both the view and the presenter (not redundant of course)) and that also doesn't work.
I admit that I'm not an expert in threading, but I can't see how there's any conflict going on here, and why RemoveListener works from controller thread, but not from the Main Thread, where the listener was actually added. Any help is appreciated!
SOLUTION
Completely by chance, I've found the solution today! It turns out that the "Invoke" call was the culprit, and it should've been BeginInvoke all this time, although this isn't mentioned anywhere in the WinForms setup guide. I'm guessing it was causing a deadlock with the controller thread and after the first GUI update it was bound to crash.
In a Windows forms Application, the following worked for me:
protected override void Dispose(bool disposing)
{
try
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
this.controller.RemoveListener(this.listener);
this.controller.Dispose();
}
}
finally
{
base.Dispose(disposing);
}
}
}
I wrote it awhile ago, though, and don't remember why it needed to be more complicated than what you tried. (Full example here: https://developer.leapmotion.com/documentation/csharp/devguide/Project_Setup_WinForms.html)
Long-running tasks are usually executed in a background thread to keep the UI from freezing. It seems the threading logic could reside in either the view or in the controller.
As an example (in C#), suppose there is a method named RunAsync that runs a delegate in a background thread, here are two ways of doing it:
// Option 1
public class View {
public void OnButtonClicked() {
RunAsync(() => controller.DoSomething());
}
}
public class Controller {
public void DoSomething() {
model.Foo();
}
}
or:
// Option 2
public class View {
public void OnButtonClicked() {
controller.DoSomething();
}
}
public class Controller {
public void DoSomething() {
RunAsync(() => model.Foo());
}
}
Is there an advantage to doing it one way or the other?
I see two arguments for the Controller having the responsibility for Thread safety.
The controller is (at least conceptually) reusable by many views. We avoid repeating ourselves but putting the RunAsync() in the Controller rather than in many Views.
Only the Controller really "knows" whether any such threading is needed. Indeed we might change the controller in future. So we have a "single responsibility" way of thinking. The controller both decides whether RunAsynch() is needed and actualy makes sure it is done.
My understanding is Controller( or ViewModel in WPF) should handle this.
View is always intended to be coupled with 'VIEW' related stuffs, thus tasks like running background job should go to controllers.
doesn't that sound odd to you that VIEW should handle this logic ?
In my opinion, it should be handled by the Controller. Since you want to separate the Model from the View as much as possible, really the View should have no idea that a particular call such as model.Foo() takes a long time and therefore needs to be run asynchronously. The Controller on the other hand is the only one that really has knowledge of both, and therefore should make the decision on whether some operation needs to run asynchronously.
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 read in many places that network connection in a j2me app should be done in a separate thread. Is this a necessity or a good to have?
I am asking this because I could not find anywhere written that this must be done in a separate thread. Also, when I wrote a simple app to fetch an image over a network and display it on screen (without using a thread) it did not work. When I changed the same to use a separate thread it worked. I am not sure whether it worked just because I changed it to a separate thread, as I had done many other changes to the code also.
Can someone please confirm?
Edit:
If running in a separate thread is not a necessity, can someone please tell me why the below simple piece of code does not work?
It comes to a stage where the emulator asks "Is it ok to connect to net". Irrespective of whether I press an "yes" or a "no" the screen does not change.
public class Moo extends MIDlet {
protected void destroyApp(boolean arg0) throws MIDletStateChangeException {
// TODO Auto-generated method stub
}
protected void pauseApp() {
}
protected void startApp() throws MIDletStateChangeException {
Display display = Display.getDisplay(this);
MyCanvas myCanvas = new MyCanvas();
display.setCurrent(myCanvas);
myCanvas.repaint();
}
class MyCanvas extends Canvas {
protected void paint(Graphics graphics) {
try {
Image bgImage = Image.createImage(getWidth(), getHeight());
HttpConnection httpConnection = (HttpConnection) Connector
.open("https://stackoverflow.com/content/img/so/logo.png");
Image image = Image.createImage(httpConnection
.openInputStream());
bgImage.getGraphics().drawImage(image, 0, 0, 0);
httpConnection.close();
graphics.drawImage(bgImage, 0, 0, 0);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Edit: I got my answer for the code here.
Edit: I spawned off a separate question of this here.
The problem is that you are trying to do work within the thread that is responsible for running the UI. If you do not use a separate thread, then that UI thread is waiting while you do your work and can't process any of your other UI updates! so yes you really should not do any significant work in event handlers since you need to return control quickly there.
I agree with Sean, but it is not required to have your network connection in a separate thread, just best practice. I think that it's probably coincidental that the connection worked properly after moving it to a separate thread. Either way though, if you want to provide any visual feedback to the user while the connection is happening (which you probably do considering the disparity of lag that users can experience on a mobile network), you should have the networked processing in a separate thread.
It is not mandatory that you do network connections in a new thread,however practically you'll find that it almost always a good idea to do so since network activities could block and leave your app in an unresponsive state.
This is an old article but it speaks about some of the issues involved in networking and user experience.