What happens in Xamarin when Forms.Init gets called and the function is already running in another thread? - xamarin

I'm thinking about how to reduce the cost of loading Forms.Init during the start of my app.
There's some work my app does that I can already do without access to Xamari.Forms. I'm thinking about loading Forms.Init in parallel in another thread.
In case that thread isn't yet finished and I already need Xamari.Forms, I'm not sure what my option are at handling the event.
What happens in Xamarin when Forms.Init gets called and the function is already running in another thread? Or are there otherwise best practices of dealing with loading Forms.Init in parallel to other work?

Forms.Init() calls the private SetupInit() which runs platform dependent code ranging from getting an Android Context, registering renderers, adding log listeners, etc...
Assembly callingAssembly = Assembly.GetCallingAssembly ();
SetupInit (activity, callingAssembly);
There are no callbacks or events tried to the competition of Init other then its synchronous completion, but there is a boolean flag that can be checked:
global::Xamarin.Forms.Forms.IsInitialized
But, depending upon platform, this flag can be set at the beginning of the method or at the end and also note there is no lock on setting this flag (which would cause a performance hit).
So, if the other code you need to run can be done completely without Forms, yes, you could do run this in parallel.
Your Application subclass and its LoadApplication step, of course, should not be done until Init() is finished.
re: https://github.com/xamarin/Xamarin.Forms

Related

Why MvxCachingFragmentCompatActivity call ExecutePendingTransactions manually?

Use mvvmcross for Xamarin.Android. Why MvxCachingFragmentCompatActivity call ExecutePendingTransactions in ShowFragment method manually? What actions done with this call? As I see, it can takes about second for several devices while navigation.
Thanks
It is basically necessary, if the next actions rely on the handling of the commit() before doing any other action.
For MVVMCross especially:
OnFragmentChanging(fragInfo, ft);
ft.Commit();
SupportFragmentManager.ExecutePendingTransactions();
OnFragmentChanged(fragInfo);
The OnFragmentChanged-Event should obviously only be called if the changes got applied. Just to take one of the code snippets out of MvxCachingFragmentCompatActivity.
From the API documentation.
After a FragmentTransaction is committed with
FragmentTransaction.commit(), it is scheduled to be executed
asynchronously on the process's main thread. If you want to
immediately executing any such pending operations, you can call this
function (only from the main thread) to do so. Note that all callbacks
and other related behavior will be done from within this call, so be
careful about where this is called from.

MFC - Add function call to mainloop?

I am fixing a MFC applivation written in C++. It is a GUI and it communicates with an external module connected to the PC via USB.
I want to avoid using a separate thread. Is there a way I can add things to the mainloop so that it runs continously rather than being event based?
I want the mainloop to make a call to a function runCommStack() in every loop.
Some possible approaches:
You can use CWnd::SetTimer to set a timer.
You can override CWinApp::OnIdle (called by CWinApp::Run).
You can override CWinApp:Run, copying and modifying the original MFC's CWinApp:Run. This definitely is not the easiest solution.
You can create a background thread.
It depends on the requirements of runCommStack(). Is this function running long times? Then you probably won't want to run it in the GUI thread. Does runCommStack need to get called every n milliseconds? Then it might also be better to run it in it's own thread. In other cases you can just use the timer or OnIdle approach.
Regarding solution 1: as Tim pointed out WM_TIMER messages are low priority messages and will not be passed to the application while other higher-priority messages are in the message queue. See also Determine priority of a window message.
With solution 2 you should remind that OnIdle will only be called if no window message is available. So this is quite the same as solution 1 (in fact a little worse).
Also keep in mind that solutions 2 and 3 might result in your runCommStack not getting called if a dialog's DoModal() is called or if a message box is displayed. This is because during MessageBox() the control is not returned to CWinApp::Run().
I'ld implement solution 1 or 4.
When there are no messages (like keys, mouse, repaint) arriving the main loop suspends the program, waiting for the next message. So the idea of adding a call to the main loop will give you very erratic operation. For example, minimizing your window will stop all the USB communication.
Using SetTimer and calling your runCommStack function in a WM_TIMER handler will probably be much more satisfactory.
You can use idle processing with CWinApp::OnIdle; this will work if reading your USB device takes only a short amount of time, otherwise the user interface will be blocked during long reads.
But using a separate thread is definitely a better method.

Outlook Addin: Working with threads

I'm working on an Outlook Addin, and I have to process a large amount of items. This takes quite a lot of time, and I therefore tried to have the processing running in a different thread (using Task.Factory.StartNew). However, that results in Outlook randomly crashing.
I'm using Redemption to work with MAPITable, in order to reduce workload and load only relevant data.
I've tried initializing my RDOSession from both my main thread, and my worker thread.
I've tried getting the MAPIFolders on the main thread, and working with only the MAPITable on the worker thread
Currently, the only thing that works for me is running all my logic on the main thread (in the button click event), however that locks Outlook's user interface for a long period of time, which is unacceptable from a user's point of view.
Does anyone have some pointer on how to work with background threads from within an Outlook Addin?
Having similar code in my project I would suggest the following:
Create new thread using the Thread class and set it apartment to STA.
Loggin to session using "session.Logon("profileName", NoMail: true, NewSession: false);" and not using MAPIOBJECT. I found it has better performance than using MAPIOBJECT, my guess is it still marshal some calls back to the main thread as MAPIOBJECT was created on the main thread.
Use "Marshal.ReleaseComObject" on each and every COM object you use as soon as you are done with them. This is probably what causing the instability as Outlook really doesn't like when it's object are left too long. For example this line of code "var table = rdoFolder.Items.MAPITable;" create two COM objects: RDOItems and MAPITable, both of them must be released so you need to split this line to hold reference to RDOItems object.
Call GC.Collect and Application.DoEvents because if you don't call Marshal.ReleaseComObject on all COM object the finalizer will try to release them and will hang because the COM objects were created on thread that don't pump message loop and it's finalizer method must run on the thread that created them.
If you can, fire a secondary process and do this loop in the separate process. This will make maximum separation between the UI and your background work.
What was the problem using RDO objects in a secondary thread? As long as RDOSession is created on the secondary thread, MAPI should be properly initialized.
Also, TaskFactory uses a thread pool, you'd be better off using an explicit Thread class, o at least make sure that RDOSession is not shared between different threads - MAPI must be initialized on each thread.

Asynchronous task that have access to XPCOM components: is it possible?

I need to create asynchronously executing task (pure JS) that is creating and working with XPCOM components (using Components.classes and Components.interfaces).
However, Worker and ChromeWorker do not have access to Components. Also, I cannot pass to them an XPCOM component created in the main thread (postMessage), as XPCOM components are not serializable.
It seems that it can be possible with nsIThread and nsIThreadManager, but documentation states that
In versions of Gecko prior to 2.0, it is possible to create real asynchronous threads.
Although this can often be accomplished without serious adverse effects, it is far from safe
and often leads to unpredictable crashes. For this reason, as of Gecko 2.0, it is no longer
possible to pass JavaScript objects from one thread to another, making the Thread Manager
unuseable from JavaScript.
and I do not want to introduce any incompatibility with Gecko 2.0.
Are there other ways to do that?
P. S. I find (Chrome)Workers hardly usable at all, as they do not have access neither to the DOM nor to Components. Why one would ever want to use them?
No, most XPCOM components are not thread-safe so that working with them from a different thread would only lead to crashes (which is why Thread Manager was rendered inaccessible to scripts). If your task contains lots of computations - use Worker to move it off the main thread and postMessage to tell the main thread access XPCOM whenever necessary. If it is mainly accessing XPCOM then it will be no use of course. You will have to do the work on the main thread and split it into small chunks to make sure that the main thread isn't being blocked. You can use nsIEventTarget.dispatch() to schedule the next processing step, something like this:
var thread = Components.classes["#mozilla.org/thread-manager;1"]
.getService(Components.interfaces.nsIThreadManager)
.currentThread;
var currentStep = -1;
function nextStep()
{
currentStep++;
//
// Execute step currentStep here
//
// Schedule next step
thread.dispatch(nextStep, thread.DISPATCH_NORMAL);
}
nextStep();
Documentation:
nsIThreadManager
nsIThread
nsIEventTarget

Windows Workflow Runtime leaks a ton of memory

Here's a overview of my workflow implementation:
GUI thread starts worker thread
worker thread analyzes some data
worker thread starts several other worker threads to work on subsets of
data
each of these last worker threads creates a workflow runtime and
executes a sequential workflow
Up until now, I've been creating a new WorkflowRuntime object in each thread like this:
using( WorkflowRuntime workflow_runtime = new WorkflowRuntime()) {
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflow_runtime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};
workflow_runtime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
WorkflowInstance instance = workflow_runtime.CreateWorkflow(typeof(MyWorkflow), parameters);
instance.Start();
waitHandle.WaitOne();
}
The reason for doing it this way is that I need to know when a specific workflow instance has been terminated or errored. The problem is that it causes a huge memory leak in my application, as mentioned here on SO.
If I use the using keyword, or even if I call Dispose and set the workflow_runtime reference to null, I get a massive memory leak. However, if I implement the workflow runtime as a Singleton, as described in this post, memory usage is very low and consistent. I can see when workflows are launched and completed by blips in the graph.
The problem is, if I use the Singleton pattern for the WF runtime, how will I know when a specific workflow has an error? If I just register the event handlers, won't all of them get called when any of the workflows get terminated or completed?
EDIT: should I just use another handle on the stack for errors, and then wait for either to be set, and then check which one was set? I should have considered that before.
So here is how I have decided to solve the problem. If there is something wrong with my solution, please post comments and I will mark someone else's answer instead, if it's correct.
I changed the code to unregister the event handlers in my previous post, and confirmed that the code was executing by setting breakpoints. After running the application, it still leaked 1.5GB.
One of my issues with the Singleton pattern is that I didn't know how to handle different instances of the workflows. It turns out that I just had to check the InstanceID of the Instance passed through the event args and make sure they matched. This is how you deal with disparate workflow events.
I implemented the Singleton pattern from http://bit.ly/8pkEWT and in addition, unregistered the event handlers and handled the InstanceIDs. The memory leak is gone! However, I haven't gotten around to validating the results of each workflow. (yikes)

Resources