Moving from monotouch to monodroid - async and threading porting - xamarin.ios

I have a small iOS app (written using monotouch) which I'm wanting to bring over monodroid. The port is causing a couple of issues, some of which are down to the way the two platforms go about doing the UI and creating classes around them.
In the iOS app there is code like this
private void BtnSomething_TouchUpInside (object sender, EventArgs e)
{
string f = this.foo;
LGPM gpm = new LGPM(Constants.a, Constants.b, f);
this.auth = new Auth("cheese", gpm);
(*) this.auth.TokenReceived += (o, e, a, aTS, r) => {
// more stuff here
};
this.PresentModalViewController(this.auth, true);
}
the auth class looks like this
public partial class Auth
{
public Auth(string m, data d)
{
this.d = d;
this.m = m;
}
// create a UIWebView and do things
Upshot - auth creates the webview, does things and returns control back to the (*) line
For monodroid, things are different as you can't really create classes like that. The best I've come up with is this
private void BtnSomething_TouchUpInside (object sender, EventArgs e)
{
string f = this.foo;
LGPM gpm = new LGPM(Constants.a, Constants.b, f);
this.auth = new Auth("cheese", gpm, context);
(*) this.auth.TokenReceived += (o, e, a, aTS, r) => {
// more stuff here
};
this.PresentModalViewController(this.auth, true);
}
then in the Auth class
public class Auth : Application
{
public Auth(string m, data d, Context c)
{
this.d = d;
this.m = m;
Intent t = new Intent(this, typeof(webview));
t.PutExtra("todo", 1);
c.StartActivity(t);
}
}
[Activity]
It's then a "normal" webview activity.
This seems to work, however, control is not return to the (*) line once the webview has completed.
The webview itself is performing an async grab of data from a website (called AuthToken), which causes an event to be thrown once it's done. I'm not sure if it's down to the difference in how classes and activities are written between the two, but in the iOS version, the event is triggered, in the Android version, it's missed.
This leads me to wonder if the way the platforms differ in how they deal with async events. Is there a tutorial somewhere on the difference between how the two platforms deal with async events?
Lots of questions I know, but threading and async events are important.
Thanks

Use startActivityForResult or another Android-ism to get the thread after some processing event.

Related

Do I need to use thread and a task in JavaFX to run something in background when a thread will do the job?

I'm using a thread to periodically run a three second background animation.
I adapted the code in question from a Thread Demo example written in Swing and used
it to replace a not quite working earlier version that used both a thread and a task.
My program stops/suspends the thread when either playing a video or running an animation
and starts a new thread when ending the video or animation. This seems to work without
any downside which is why I'm puzzled why my earlier JavaFX searches hadn't turned up
a similar solution to the one I'm using. It seems a rather direct approach for running
short, simple background animations.
Where am I going wrong with this? What am I missing? How would I rewrite this code
using both a Thread and a Task or do I need to?
I should add - the while and run statements are virtually unchanged from the original
and the only significant addition to the Swing code was to add thread.setDaemon( true )
to startThread().
A podcast listener.
// background thread
class BackGround extends Thread {
#Override
public void run() {
while ( suspend.getValue() == false ) {
try {
int r = shared.randInt( 5, 10 );
Thread.sleep( r * 1000 );
} catch ( InterruptedException e ) {
// do nothing
}
if ( suspend.getValue() == false ) {
Platform.runLater( () -> {
int g = shared.cssGradients.length - 1;
g = shared.randInt( 0, g );
gradientColor.set( shared.cssGradients[g] );
Boolean bif = shared.updatePanes( shared.cssGradients[g],
leftPane, rightPane );
});
}
}
}
} // class background
// start thread
public synchronized void startThread() {
thread = new BackGround(); // Thread thread ...defined elsewhere
thread.setDaemon( true );
thread.start();
}
// stop thread
public synchronized void stopThread() {
suspend.set( true );
}
The reason the Task class is useful for JavaFX is that it provides a number of callbacks like succeeded(), failed() or cancelled() and methods like updateProgress() and updateMessage() that will run in the JavaFX Application thread and therefore let you update the UI without Platform.runLater( () -> { ... }); This makes the Task class a perfect choice for doing background tasks like downloading data or long running computations.
However, since your thread simply runs continuously without ever really finishing its work, it doesn't seem that you would need any of the additional functionality a Task would provide you with over a simple Thread.
Still, if you really wanted to convert your code to use a Task, it would look just like this:
class BackGround extends Task<Void> {
#Override
protected Void call() throws Exception {
while (suspend.getValue() == false) {
try {
int r = shared.randInt(5, 10);
Thread.sleep(r * 1000);
} catch (InterruptedException e) {
// do nothing
}
if (suspend.getValue() == false) {
Platform.runLater(() -> {
int g = shared.cssGradients.length - 1;
g = shared.randInt(0, g);
gradientColor.set(shared.cssGradients[g]);
Boolean bif = shared.updatePanes(shared.cssGradients[g],
leftPane, rightPane);
});
}
}
return null;
}
}
// start thread
public synchronized void startThread() {
Task<Void> bg = new BackGround();
Thread taskThread = new Thread(bg);
taskThread.setDaemon(true);
taskThread.start();
}
// stop thread
public synchronized void stopThread() {
suspend.set( true );
}
As you see, it really doesn't make a difference for you, as you don't need anything that a Thread couldn't give you. If however you wanted to have closer communication with the UI thread, e.g. showing a progress bar or showing status updates, then a Task would give you the tools to do that.
I guess its also worth mentioning that the use of a Timeline would be quite elegant for triggering your animations. It would look somewhat like this:
Timeline timeline = new Timeline(new KeyFrame(Duration.seconds(1), new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
int g = shared.cssGradients.length - 1;
g = shared.randInt(0, g);
gradientColor.set(shared.cssGradients[g]);
Boolean bif = shared.updatePanes(shared.cssGradients[g], leftPane, rightPane);
}
}
));
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
The code inside the handle() method is run every second in the JavaFX Application thread. Unfortunately this only lets you set a fixed time between executions, while you seem to want to wait a random amount of time each time.
TL;DR: Using a Thread is ok, because you don't need the additional functionalities of a Task in your use case.

JADE AchieveREInitiator not working properly. prepareRequests is not called

I am currently using JADE to build an agent-based platform to solve scheduling problems. The case is that, a defined behaviour extends AchieveREInitiator doesn't work properly in some specific state of the programme.
This is the behaviour class:
class ACOInitiator extends AchieveREInitiator {
Agent myAgent;
List<Schedule> roundSchedules;
public ACOInitiator(Agent a, ACLMessage msg) {
super(a, msg);
this.myAgent = a;
roundSchedules = new ArrayList<Schedule>();
System.out.println(msg.getContent()); //This is properly printed.
// TODO Auto-generated constructor stub
}
#Override
protected Vector prepareRequests(ACLMessage request) {
System.out.println(request.getContent()); //In some specific state, this is not printed.
Vector v = new Vector(1);
for (int i = 1; i <= Properties.antNum; i++) {
AID aAID = new AID("Ant" + i, AID.ISLOCALNAME);
request.addReceiver(aAID);
aAID = null;
}
v.addElement(request);
return v;
}
#Override
protected void handleAgree(ACLMessage agree) {
try {
roundSchedules.add((Schedule) (agree.getContentObject()));
} catch (UnreadableException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
agree = null;
}
#Override
protected void handleAllResponses(Vector responses) {
Collections.sort(roundSchedules);
Environment.iterSolution = roundSchedules.get(0);
roundSchedules = null;
Environment.setState(Environment.STATE_ITERATION_CHECKING);
responses = null;
myAgent.removeBehaviour(this);
}
}
When the programme is executed, the following results are shown:
Generate solution.
Generate solution.
Iteration #1: 788.0(0.48s) (New best solution)
Generate solution.
Generate solution.
Iteration #2: 809.0(0.12s) r = 1/2
Generate solution.
Generate solution.
Iteration #3: 793.0(0.08s) r = 2/2
......
----- Simulation starts -----
......
#120
Breakdown machines:
Repaired machines:
Incoming jobs: 2-5;
Generate solution.
----- All schemes finished -----
This is unwanted. Apparently, the two Strings to be printed is the same. That's why every iteration in the solution stage, 2 "Generate solution." are printed. However, in the later simulation stage, only 1 "Generate solution." is printed and the programmes goes to the end. It can be inferred that the "prepareRequests" method in not auto called, as in earlier stage.
I'm new to JADE and the problem has bothered me a couple of days. Please help if you are a JADE programmer.
I'm not sure I understand your question or problem but from what I can see the first printout "Generate solution" happens in the constructor:
public ACOInitiator(Agent a, ACLMessage msg) { -> System.out.println(msg.getContent())
the second one in the prepare requests method:
protected Vector prepareRequests(ACLMessage request) {-> System.out.println(msg.getContent())
.
Also remember when interacting with multiple agents the initiator behaviour will wait for a response from all its responder behaviours.
Hope this helps, if it does not, try attaching sniffer diagrams.

c# wanting multiple ui threads but getting cross-reference errors instead

i'm still very new at c#, threads and forms. i'm writing a small data acquistion program. it has two threads: the main ui thread and a sensor polling/logging/charting thread. when the user clicks the "start-logging" button, it it continuously polls the sensors (over a virtual COM port), writes the response to a file, updates the main form with some basic polling stats (how many pollings per second). if the user has clicked a "monitor" button, it opens a charting form and the polling thread invokes a methods that that adds the sensors values to the chart.
i have a version of this program that works very well but i found that if i have multiple charts open (so that i can view multiple sensors in realtime), the chart updates become sporadic or stop and only the window with the focus updates smoothly. (the comm port is only 56kbaud so it's not like the polling is being swamped with data.)
so i got the "bright" idea to make charting threads, thinking this would provide multiple UI loops and would produce nice smooth charting on multiple chart forms. below is simplified code; e.g. here, the charting thread is started with the polling thread instead of when the user clicks the "monitor" button. it compiles, but when it runs, i get a cross-reference error at the point when the update_chart method is called.
seems i have a fundamental misunderstanding of several things about threads and control ownership. the chart was made in the "charting" thread, but when the "polling" thread invokes the update_chart method, the code shows that update_chart methods is being run by the "main_ui" thread. i'm open to any suggestions/advise that'll give me smooth charting and stats updates. thanks.
namespace WindowsFormsApplication1
{
public partial class Main_Form : Form
{
delegate void UpdateUIStatsDelegate(string update);
UpdateUIStatsDelegate update_stats_delegate;
static BackgroundWorker polling_thread = new BackgroundWorker();
static BackgroundWorker charting_thread = new BackgroundWorker();
public static Chart_Form chart_form = new Chart_Form();
public Main_Form()
{
Thread.CurrentThread.Name = "main_ui";
update_stats_delegate = new UpdateUIStatsDelegate(update_stats);
polling_thread.DoWork += polling_thread_DoWork;
charting_thread.DoWork += charting_thread_start;
}
private void start_logging_Click(object sender, EventArgs e)
{
start_polling_thread();
start_charting_thread();
}
private void start_polling_thread()
{
polling_thread.RunWorkerAsync();
}
private void polling_thread_DoWork(object sender, DoWorkEventArgs e)
{
string sensor_values;
Thread.CurrentThread.Name = "polling";
while (true)
{
sensor_values = poll_the_sensors_and_collect_the_responses();
log_to_file(sensor_values);
// BeginInvoke(chart_form.update_chart_delegate, new object[] { sensor_values });
chart_form.BeginInvoke(chart_form.update_chart_delegate, new object[] { sensor_values });
pps = compute_polling_performance();
BeginInvoke(update_stats_delegate, new object[] { pps.ToString("00") });
}
}
private void update_stats(string stat)
{
string tn = Thread.CurrentThread.Name;
// this says "main_ui", but i don't get a cross-reference error
pollings_per_second.Text = stat;
}
private void start_charting_thread()
{
charting_thread.RunWorkerAsync();
}
private void charting_thread_start(object sender, DoWorkEventArgs e)
{
Thread.CurrentThread.Name = "charting";
Chart_Form chart_form = new Chart_Form();
chart_form.Show();
while (charting_is_active) { }
}
}
public partial class Chart_Form : Form
{
public delegate void UpdateChartDelegate(string sensor_values);
public UpdateChartDelegate update_chart_delegate;
public Chart_Form()
{
string tn = Thread.CurrentThread.Name;
update_chart_delegate = new UpdateChartDelegate(update_chart);
this.Text = "a realtime plot of sensor values";
}
private void update_chart(string sensor_values)
{
string tn = Thread.CurrentThread.Name;
// this says "main_ui" and i get a cross reference error; set below.
int x = extract_x_value(sensor_values);
int y = extract_y_value(sensor_values);
chart1.Series[X_AXIS].Points.AddY(x); // <<--- i get a cross-reference runtime error here...
chart1.Series[Y_AXIS].Points.AddY(y);
}
}
}

Create Extension method for IObservable

I need to bring some data into an IObservable stream. I want to use an extension method on IObservable to do this, but i am not sure how to do it.
The data is produced by a simple class that has this signature:
interface Process<TIn, TOut> {
void Do(TIn data);
event Action<TOut> Result;
}
i.e. to start the process I have to call Do(...) and the result is sent to the event Result(...). This can't be changed!
I want to bring this data into an Rx process, that handles user input in this way:
subject.AsObservable<string> // this produces the observable of user inputs
.Throttle(TimeSpan.FromMilliseconds(typingDelay))
.DistinctUntilChanged()
.Process(myProcess) // this is what I need help for
.Switch()
.Subscribe(myConsumer)
This is from adopted from the standard example of delayed user input triggering a web service (or something else that is long-running and has to be async) in the Hands-on Labs.
Whenever the user continues to enter, all observables that are still "underway" must be cancelled (therefore the Switch()). So my Process() has to return an IObservable<IObservable<TOut>> to make the switch work correctly.
I'm really stuck here. Does anyone has a hint for me how to write this Process(...) extension method?
I've modified your Process interface to use generics properly and provided a dummy implementation of the interface like so:
interface IProcess<T, R>
{
void Do(T data);
event Action<IEnumerable<R>> Result;
}
public class ProcessImpl<T, R> : IProcess<T, R>
{
public void Do(T data) { }
public event Action<IEnumerable<R>> Result;
}
Now you can write the extension method like this:
public static IObservable<IObservable<R>> Process<T, R>(this T #this)
{
return Observable.Create<IObservable<R>>(o =>
{
var p = new ProcessImpl<T, R>();
var subscription =
Observable
.FromEvent<IEnumerable<R>>(
h => p.Result += h,
h => p.Result -= h)
.Take(1)
.Select(x => x.ToObservable())
.Subscribe(o);
p.Do(#this);
return subscription;
});
}
Does this work for you?
Basically, your Process extension method needs to subscribe to the source observable and output another. Something like:
public static IObservable<TOut> Process<TIn, TOut>(this IObservable<TIn> source, IProcess<TIn, TOut> processor)
{
return Observable.Create((IObserver<TOut> obs) =>
{
var sourceSub = source.Subscribe(processor.Do);
var outSub = Observable.FromEvent<TOut>(h => processor.Result += h,
h => processor.Result -= h)
.Subscribe(obs);
return new System.Reactive.Disposables.CompositeDisposable(sourceSub, outSub);
});
}
I don't think that Switch will do what you are hoping it will. All Switch will do is end one subscription when another observable becomes available. However, ending the subscription cannot cancel any running calls to the interface method Process.Do. The cancellation you are talking about will need to be handled by the interface implementation itself.

Threading multiple async calls

Part of my Silverlight application requires data from three service requests. Up until now I've been chaining the requests so as one completes the other starts... until the end of the chain where I do what I need to do with the data.
Now, I know thats not the best method(!). I've been looking at AutoResetEvent (link to MSDN example) to thread and then synchronize the results but cannot seem to get this to work with async service calls.
Does anyone have any reason to doubt this method or should this work? Code samples gratefully received!
Take a look at this example:
Will fire Completed event and print 'done' to Debug Output once both services returned.
Key thing is that waiting for AutoResetEvents happens in background thread.
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
Completed += (s, a) => { Debug.WriteLine("done"); };
wrk.DoWork += (s, a) =>
{
Start();
};
wrk.RunWorkerAsync();
}
public event EventHandler Completed;
private void Start()
{
auto1.WaitOne();
auto2.WaitOne();
Completed(this, EventArgs.Empty);
}
public AutoResetEvent auto1 = new AutoResetEvent(false);
public AutoResetEvent auto2 = new AutoResetEvent(false);
BackgroundWorker wrk = new BackgroundWorker();
private void Button_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.Service1Client clien = new SilverlightAsyncTest.ServiceReference1.Service1Client();
clien.DoWorkCompleted += new EventHandler<SilverlightAsyncTest.ServiceReference1.DoWorkCompletedEventArgs>(clien_DoWorkCompleted);
clien.DoWork2Completed += new EventHandler<SilverlightAsyncTest.ServiceReference1.DoWork2CompletedEventArgs>(clien_DoWork2Completed);
clien.DoWorkAsync();
clien.DoWork2Async();
}
void clien_DoWork2Completed(object sender, SilverlightAsyncTest.ServiceReference1.DoWork2CompletedEventArgs e)
{
Debug.WriteLine("2");
auto1.Set();
}
void clien_DoWorkCompleted(object sender, SilverlightAsyncTest.ServiceReference1.DoWorkCompletedEventArgs e)
{
Debug.WriteLine("1");
auto2.Set();
}
}
It could be done using the WaitHandle in the IAsyncResult returned by each async method.
The code is simple. In Silverlight I just do 10 service calls that will add an item to a ListBox. I'll wait until all the service calls end to add another message to the list (this has to run in a different thread to avoid blocking the UI). Also note that adding items to the list have to be done through the Dispatcher since they will modify the UI. There're a bunch of lamdas, but it's easy to follow.
public MainPage()
{
InitializeComponent();
var results = new ObservableCollection<string>();
var asyncResults = new List<IAsyncResult>();
resultsList.ItemsSource = results;
var service = new Service1Client() as Service1;
1.To(10).Do(i=>
asyncResults.Add(service.BeginDoWork(ar =>
Dispatcher.BeginInvoke(() => results.Add(String.Format("Call {0} finished: {1}", i, service.EndDoWork(ar)))),
null))
);
new Thread(()=>
{
asyncResults.ForEach(a => a.AsyncWaitHandle.WaitOne());
Dispatcher.BeginInvoke(() => results.Add("Everything finished"));
}).Start();
}
Just to help with the testing, this is the service
public class Service1
{
private const int maxMilliSecs = 500;
private const int minMillisSecs = 100;
[OperationContract]
public int DoWork()
{
int millisSecsToWait = new Random().Next(maxMilliSecs - minMillisSecs) + minMillisSecs;
Thread.Sleep(millisSecsToWait);
return millisSecsToWait;
}
}

Resources