How is async network I/O handled with a WP7 Scheduled Task? - windows-phone-7

With Mango, it's possible to create a scheduled task to update the ShellTiles data.
It's up to the task to call NotifyComplete() when it's done.
Given that I/O on the phone should be asynchronous, how do you ensure that your I/O is complete prior to calling NotifyComplete()?
Via synchronization primatives? Or will the I/O be allowed to complete once the Task has notified the phone's OS it's complete?
Sync primatives is the obvious answer, but on the phone, blocking isn't really a good choice.

Scheduled tasks are not executed synchronously. They are started and then have 15 seconds to call NotifyComplete (or abort) before they are forcefully terminated.
In direct answer to your question, you would use the asynchronous IO methods and then call NotifyComplete from the complete event or callback.
Here's an example. I've used the Microsoft.Phone.Reactive stuff but you can use Begin/EndGetResponse in the traditional way if you prefer.
public class SampleTask : ScheduledTaskAgent
{
protected override void OnInvoke(ScheduledTask task)
{
HttpWebRequest request = WebRequest.CreateHttp("http://stackoverflow.com");
Observable.FromAsyncPattern<WebResponse>(
request.BeginEndResponse,
request.EndGetResponse
)()
.Subscribe(response =>
{
// Process the response
NotifyComplete();
}, ex =>
{
// Process the error
Abort(); // Unschedules the task (if the exception indicates
// the task cannot run successfully again)
});
// Synchronous control flow will continue and exit the OnInvoke method
}
}

Related

VSTO Outlook: How to perform a long task without blocking the Outlook main UI thread

When the "To" field losew the focus from the compose window I need to perform a long task which takes some time to be completed. Now UI is getting blocked because I do it in the main UI thread so I would like to make it non-blocking. I have thought in using the async/await commands from C# as below:
public async void PerformLongTask()
{
bool result = await Task.Run(() =>
{
// Long task here
});
}
I would like to know if this is the correct way to do an asynchronous task without blocking the main UI thread in Outlook or is there some other better way to do it? If so, how? When you need to perform such long task and you need to be non-blocking, how do you usually do it?
async/await or tasks are fine in Outlook as long as you don't touch any Outlook Object Model objects on that secondary thread.
If you need to touch OOM objects, do so by switching to the main thread using, for example, the Dispatcher object - retrieve it on the main thread from Dispatcher.CurrentDispatcher, then using Dispatcher.Invoke/InvokeAsync whenever you need to do anything with Outlook objects. Since thread switching is expensive, try to batch multiple OOM hits into a single Invoke.
public async void PerformLongTask()
{
var dispatcher = Dispatcher.CurrentDispatcher;
bool result = await Task.Run(() =>
{
// Long task here
//now use OOM on the main thread
dispatcher.Invoke(() =>
{
MessageBox.Show(Globals.ThisAddIn.Application.Version);
});
});
}

Why use Device.BeginInvokeOnMainThread() in a Xamarin application?

My code looks like this:
public void Init() {
if (AS.pti == PTI.UserInput)
{
AS.runCardTimer = false;
}
else
{
AS.runCardTimer = true;
Device.BeginInvokeOnMainThread(() => showCards().ContinueWith((arg) => { }));
}
}
The Init method is called from the constructor. Can someone please explain to me why the developer might have added the Device.BeginInvokeOnMainThread() instead of just calling the method showCards?
Also what does the ContinueWith((arg)) do and why would that be included?
The class where this Init() method is might be created on a background thread. I'm assuming showCards() are updating some kind of UI. UI can only be updated on the UI/Main thread. Device.BeginInvokeOnMainThread() ensures that the code inside the lambda is executed on the main thread.
ContinueWith() is a method which can be found on Task. If showCards() returns a task, ContinueWith() makes sure the task will complete before exiting the lambda.
UI actions must be performed on UI thread (different name for main thread). If you try to perform UI changes from non main thread, your application will crash. I think developer wanted to make sure it will work as intended.
The simple answer is: Background thread cannot modify UI elements because most UI operations in iOS and Android are not thread-safe; therefore, you need to invoke UI thread to execute the code that modifies UI such MyLabel.Text="New Text".
The detailed answer can be found in Xamarin document:
For iOS:
IOSPlatformServices.BeginInvokeOnMainThread() Method simply calls NSRunLoop.Main.BeginInvokeOnMainThread
public void BeginInvokeOnMainThread(Action action)
{
NSRunLoop.Main.BeginInvokeOnMainThread(action.Invoke);
}
https://developer.xamarin.com/api/member/Foundation.NSObject.BeginInvokeOnMainThread/p/ObjCRuntime.Selector/Foundation.NSObject/
You use this method from a thread to invoke the code in the specified object that is exposed with the specified selector in the UI thread. This is required for most operations that affect UIKit or AppKit as neither one of those APIs is thread safe.
The code is executed when the main thread goes back to its main loop for processing events.
For Android:
Many People think on Xamarin.Android BeginInvokeOnMainThread() method use Activity.runOnUiThread(), BUT this is NOT the case, and there is a difference between using runOnUiThread() and Handler.Post():
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);//<-- post message delays action until UI thread is scheduled to handle messages
} else {
action.run();//<--action is executed immediately if current running thread is UI thread.
}
}
The actual implementation of Xamarin.Android BeginInvokeOnMainThread() method can be found in AndroidPlatformServices.cs class
public void BeginInvokeOnMainThread(Action action)
{
if (s_handler == null || s_handler.Looper != Looper.MainLooper)
{
s_handler = new Handler(Looper.MainLooper);
}
s_handler.Post(action);
}
https://developer.android.com/reference/android/os/Handler.html#post(java.lang.Runnable)
As you can see, you action code is not executed immediately by Handler.Post(action). It is added to the Looper's message queue, and is handled when the UI thread's scheduled to handle its message.

Handling configuration change for async methods

I have an activity which has an async method in it. This async method is long running. After the async method returns, the UI needs to be updated and some of the controls reference the activity.
At the moment, everything works correctly if you do not have a configuration change (like screen rotation) while the async task is running. However, if a configuration change happens while it is running, then the exception Activity is destroyed is thrown and the UI is not updated. From what reading I have done, this seems to be because the async method captures context and then tries to update the old context which is of course destroyed after the configuration change.
My question is: What are the best ways to solve this problem or at worst case scenario work around it?
I personally think you have only three options
You can disable rotation permanently or temporary, but this is a bad practice
To disable it permanently set ConfigurationChanges
[Activity(Label = "...", ConfigurationChanges = Android.Content.PM.ConfigChanges.KeyboardHidden | Android.Content.PM.ConfigChanges.Orientation | Android.Content.PM.ConfigChanges.ScreenSize)]
To disable it temporary while task working you should disable rotation handling,
disable
this.RequestedOrientation = Android.Content.PM.ScreenOrientation.Nosensor;
enable
this.RequestedOrientation = Android.Content.PM.ScreenOrientation.Sensor;
If you are using fragment you can prevent fragment destroy with RetainInstance = true. That might work, but i never tested it.
You can cancel task with CancelationToken and restart it in OnRestoreInstanceState()
Here is example how to cancel task
{
CancellationTokenSource cts;
...
// If a download process is already underway, cancel it.
if (cts != null)
{
cts.Cancel();
}
// Now set cts to cancel the current process if the button is chosen again.
CancellationTokenSource newCTS = new CancellationTokenSource();
cts = newCTS;
try
{
//Send cts.Token to carry the message if there is a cancellation request.
await AccessTheWebAsync(cts.Token);
}
// Catch cancellations separately.
catch (OperationCanceledException)
{
ResultsTextBox.Text += "\r\nDownloads canceled.\r\n";
}
catch (Exception)
{
ResultsTextBox.Text += "\r\nDownloads failed.\r\n";
}
// When the process is complete, signal that another process can proceed.
if (cts == newCTS)
cts = null;
}
And in the task
async Task AccessTheWebAsync(CancellationToken ct)
{
...
// Retrieve the website contents from the HttpResponseMessage.
byte[] urlContents = await response.Content.ReadAsByteArrayAsync();
// Check for cancellations before displaying information about the
// latest site.
ct.ThrowIfCancellationRequested();
...
}
There are plenty of things you could do, but please don't go and disable the phones ability to turn the screen -- that is just going to ignore your users.
At a highlevel you will have to do two things:
Make sure the async task keeps running and is not restarted if the activity dies.
You can solve that by moving the task either into the application class or (cleaner) into a headless fragment with setRetainInstance set to true.
In the onDestroy method in the activity, remove it from the async task, in the onCreate task give the activity to the async task (if it exist).
This is what prevents the async task from calling the old context and can be done with a simple java setter on the async task. Don't forget to cache the result in the task if the activity is currently not connected.
In the end what I ended up doing was encapsulating the async task in another class which held a reference to the current activity, which implemented and interface which defined a method which handles the async response and updates the UI.
The activity held a static variable of the encapsulated async task, and if it was running during a config change, the encapsulated async's task reference to the activity was updated to the new activity.

How can a JSF/ICEfaces component's parameters be updated immediately?

I have an ICEfaces web app which contains a component with a property linked to a backing bean variable. In theory, variable value is programmatically modified, and the component sees the change and updates its appearance/properties accordingly.
However, it seems that the change in variable isn't "noticed" by the component until the end of the JSF cycle (which, from my basic understanding, is the render response phase).
The problem is, I have a long file-copy operation to perform, and I would like the the inputText component to show a periodic status update. However, since the component is only updated at the render response phase, it doesn't show any output until the Java methods have finished executing, and it shows it all changes accumulated at once.
I have tried using FacesContext.getCurrentInstance().renderResponse() and other functions, such as PushRenderer.render(String ID) to force XmlHttpRequest to initialize early, but no matter what, the appearance of the component does not change until the Java code finishes executing.
One possible solution that comes to mind is to have an invisible button somewhere that is automatically "pressed" by the bean when step 1 of the long operation completes, and by clicking it, it calls step 2, and so on and so forth. It seems like it would work, but I don't want to spend time hacking together such an inelegant solution when I would hope that there is a more elegant solution built into JSF/ICEfaces.
Am I missing something, or is resorting to ugly hacks the only way to achieve the desired behavior?
Multithreading was the missing link, in conjunction with PushRenderer and PortableRenderer (see http://wiki.icesoft.org/display/ICE/Ajax+Push+-+APIs).
I now have three threads in my backing bean- one for executing the long operation, one for polling the status, and one "main" thread for spawning the new threads and returning UI control to the client browser.
Once the main thread kicks off both execution and polling threads, it terminates and it completes the original HTTP request. My PortableRenderer is declared as PortableRender portableRenderer; and in my init() method (called by the class constructor) contains:
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
For the threading part, I used implements Runnable on my class, and for handling multiple threads in a single class, I followed this StackOverflow post: How to deal with multiple threads in one class?
Here's some source code. I can't reveal the explicit source code I've used, but this is a boiled-down version that doesn't reveal any confidential information. I haven't tested it, and I wrote it in gedit so it might have a syntax error or two, but it should at least get you started in the right direction.
public void init()
{
// This method is called by the constructor.
// It doesn't matter where you define the PortableRenderer, as long as it's before it's used.
PushRenderer.addCurrentSession("fullFormGroup");
portableRenderer = PushRenderer.getPortableRenderer();
}
public void someBeanMethod(ActionEvent evt)
{
// This is a backing bean method called by some UI event (e.g. clicking a button)
// Since it is part of a JSF/HTTP request, you cannot call portableRenderer.render
copyExecuting = true;
// Create a status thread and start it
Thread statusThread = new Thread(new Runnable() {
public void run() {
try {
// message and progress are both linked to components, which change on a portableRenderer.render("fullFormGroup") call
message = "Copying...";
// initiates render. Note that this cannot be called from a thread which is already part of an HTTP request
portableRenderer.render("fullFormGroup");
do {
progress = getProgress();
portableRenderer.render("fullFormGroup"); // render the updated progress
Thread.sleep(5000); // sleep for a while until it's time to poll again
} while (copyExecuting);
progress = getProgress();
message = "Finished!";
portableRenderer.render("fullFormGroup"); // push a render one last time
} catch (InterruptedException e) {
System.out.println("Child interrupted.");
}
});
statusThread.start();
// create a thread which initiates script and triggers the termination of statusThread
Thread copyThread = new Thread(new Runnable() {
public void run() {
File someBigFile = new File("/tmp/foobar/large_file.tar.gz");
scriptResult = copyFile(someBigFile); // this will take a long time, which is why we spawn a new thread
copyExecuting = false; // this will caue the statusThread's do..while loop to terminate
}
});
copyThread.start();
}
I suggest looking at our Showcase Demo:
http://icefaces-showcase.icesoft.org/showcase.jsf?grp=aceMenu&exp=progressBarBean
Under the list of Progress Bar examples is one called Push. It uses Ajax Push (a feature provided with ICEfaces) to do what I think you want.
There is also a tutorial on this page called Easy Ajax Push that walks you through a simple example of using Ajax Push.
http://www.icesoft.org/community/tutorials-samples.jsf

How to implement kind of global try..finally in TPL?

I have async method that returns Task. From time to time my process is recycling/restarting. Work is interruping in the middle of the Task. Is there more or less general approach in TPL that I can at least log that Task was interruped?
I am hosting in ASP.NET, so I can use IRegisteredObject to cancel tasks with CancellationToken. I do not like this however. I need to pass CancellationToken in all methods and I have many of them.
try..finally in each method does not seem even to raise. ContinueWith also does not work
Any advice?
I have single place I start my async tasks, however each task can have any number of child tasks. To get an idea:
class CommandRunner
{
public Task Execute(object cmd, Func<object, Task> handler)
{
return handler(cmd).ContinueWith(t =>
{
if (t.State = == TaskStatus.Faulted)
{
// Handle faultes, log them
}
else if (x.Status == TaskStatus.RanToCompletion)
{
// Audit
}
})
}
}
Tasks don't just get "interrupted" somehow. They always get completed, faulted or cancelled. There is no global hook to find out about those completions. So the only option to do your logging is to either instrument the bodies of your tasks or hook up continuations for everything.

Resources