I have written an outlook add-in to filter spam. The issue is that when the add-in is doing its job of processing a message, and especially with a large attachment that it is procesing / reading through, it is taking a lot of time and because of this the main outlook UI is un-responsive and users cannot do anything with the UI.
Is there an asynchrounous way of running the add-in processing, so that the outlook UI remains OK.
The add-in does a lot of things dueing its procesing of each message and hence it takes a lot of time.
Creating another thread won't help you if the bulk of the time is being spent in the Outlook API. Due to the threading model in Outlook, accessing the object model from another thread will cause the call to be marshalled to the main thread which means now your UI is still frozen and your background thread is blocking.
If most of the work is spent doing things that don't touch the Outlook object model, you'll probably see a significant improvement spinning off a separate worker thread (or thread pool) to process the attachments you've saved.
It's just like with any other program basically. If you need to do something outside of the main thread do so (i.e. create another thread). There's no Outlook-specific API or framework, though.
You have to be extra careful about exception handling though. Unhandled exceptions escaping from a thread can have the weirdest results (though in most cases Outlook will simply crash).
Also, if at all possible you should try to avoid or at least drastically limit accessing the Outlook Object Model from within your processing thread.
Finally, another thing you should make sure of is that you explicitly call CoInitializeEx / CoUninitialize specially for your new thread if it in any way directly or indirectly uses COM-related functions.
Related
I apologize if there's an obvious answer to this, but I just haven't located it yet.
I'm creating an application that loads some information from a database when the user navigates into an Explorer directory. I'm doing this on a background worker thread (using ATL's CWorkerThread), and calling SetEvent when the navigation occurs. When the background thread is done loading the data, it posts a custom message to a message-only window back on the UI thread. Then the UI thread can do stuff with the loaded info if it wants.
Of course, if the user navigates into a directory, and the worker-thread starts working, but the user quickly navigates away, the current worker-thread task is no longer necessary. So the task should be either cancelled if in progress, or if the worker thread has already posted its completion message to the UI thread, the UI thread should be prepared to check it and ignore it, since it's now stale.
My question is whether there is a nice design pattern and helpful example for this type of situation. I think I've seen situations in which a looping worker thread checks a boolean (like fCancelled) to see if it should still continue doing something. But how about when the completion message is already posted? Is there any standard way in which the worker thread and UI thread can communicate that the message is stale and should be disregarded?
Thank you very much for any input.
I have an add-in which needs to run some time consuming code during start up, since Outlook disables slow add-ins, what to avoid this somehow. Are there events I can respond to we don't count in Outlooks calculation of a slow add in? Or is utilizing threads the only way to go? Am a bit worried that threads if not used very carefully may interact badly with Outlook.
Don't do anything like that on startup - the easiest workaround is to create a Timer object (use the Timer object from the Forms namespace, not System - you want the timer to fire on the main thread) and run your code when the timer event fires. By the time the event fires, you will be out of the startup callback that Outlook monitors, so it will never know. The user would still be blocked of course, so this can be only a temporary band-aid.
You can still use threads in you addin, you just need to make sure you don't touch OOM on the secondary threads. If your time consuming code does not need any Outlook objects, you can easily move it into a secondary thread. Otherwise Extended MAPI (C++ or Dephi only) or Redemption (I am its author - it wraps Extended MAPI and can be used from any language) are your only options. In case of Redemption, you can save the value of the Namespace.MAPIOBJECT property in a variable and then on a secondary thread create a new instance of the RDOSession object (it roughly corresponds to the Namespace object in OOM) and set its MAPIOBJECT property to the value saved on the main thread.
I have an app which needs almost no user interaction, but requires Geofences. Can I run this entirely within a background service?
There will be an Activity when the service is first run. This Activity will start a service and register a BroadcastReceiver for BOOT_COMPLETED, so the service will start at boot. It's unlikely that this Activity will ever be run again.
The service will set an Alarm to go off periodically, which will cause an IntentService to download a list of locations from the network. This IntentService will then set up Geofences around those locations, and create PendingIntents which will fire when the locations are approached. In turn, those PendingIntents will cause another IntentService to take some action.
All this needs to happen in the background, with no user interaction apart from starting the Activity for the first time after installation. Hence, the Activity will not interact with LocationClient or any location services.
I've actually got this set up with proximityAlerts, but wish to move to the new Geofencing API for battery life reasons. However, I have heard that there can be a few problems with using LocationClient from within a service. Specifically, what I've heard (sorry, no references, just hearsay claims):
location client relies on ui availability for error handling
when called from background thread, LocationClient.connect() assumes that it is called from main ui thread (or other thread with event looper), so connection callback is never called, if we call this method from service running in background thread
When I've investigated, I can't see any reason why this would be the case, or why it would stop my doing what I want. I was hoping it would be almost a drop-in replacement for proximityAlerts...
Can anyone shed some light on things here?
The best thing would be to just try it out, right? Your strategy seems sound.
when called from background thread, LocationClient.connect() assumes that it is called from main ui thread (or other thread with event looper), so connection callback is never called, if we call this method from service running in background thread.
I know this to be not true. I have a Service that is started from an Activity, and the connection callback is called.
I dont know about proximity alerts; but I cant seem to find an API to list my GeoFences. I am worried that my database (sqlite) and the actual fences might get out of sync. That is a design flaw in my opinion.
The reason LocationClient needs UI, is that the device may not have Google Play Services installed. Google has deviced a cunning and complex mechanism that allows your app to prompt the user to download it. The whole thing is horrible and awful in my opinion. Its all "what-if what-if" programming.
(They rushed a lot of stuff out the door for google IO 2013. Not all of it are well documented, and some of it seems a bit "rough around the edges").
We have a system where there are typically two processes running on the same system. One process handles the GUI and the other runs like a service (although for historical reasons, it's not a service, just an exe with no visible window).
The two processes undertake IPC mainly via registered messages asynchronously - i.e. we use RegisterWindowMessage() in both processes to define a large'ish set of messages that effectively form the API to the server process.
I have written a "hands-free" monitoring application that uses SetWindowsHookEx() to monitor and display the message queues of both processes and provide some level of decoding of the way the API is being utilised and how notifications are being propagated to the GUI process (each individual window can subscribe to notifications from the server directly).
So, there are a large number of messages in both directions so I have filtering and summary counts etc. so I can focus on particular activity. All this can be done without affecting the live code, which is good.
This all works well, but it now would be very useful to be able to "tag" a message originating in the GUI so I can trace the same message when it's processed by the server. This would be enormously useful for debugging and diagnosing system issues, but I can't find a clean way (actually I can't find any way!) of doing this without adding such support to our registered message API, which would be a lot of work and involves more risk than I'm comfortable with at the moment. It gets further complicated by the fact that the server pre-processes some messages and then does a PostMessage() back to itself to perform the action, so the originating message can get "lost".
Has anyone here tackled this type of problem? If so, can you give me some pointers? If not, then are there any documented or undocumented ways of adding a small block of data to a Windows message and retrieving it later? I've looked at SetMessageExtraInfo() but that seems to be per-queue rather than per-message.
FindWindow or FindWindowEx will give you the details of the GUI Window. Compare the details with message intercepted
Our code library needs to be notified when the application is exiting. So we have subscribed to the System.Window.Forms.Application.ApplicationExit event. This works nicely for Winforms apps, but does it also work for other types of applications such as console apps, services, and web apps (such as ASP.NET)? The namespace would suggest that it doesn't, and it presumably gets raised when Application.Exit() is called (explicitly or implictly), which may not be correct to call for these other cases.
Is there some other event which would be better in these other cases or which would be more universal (great if it works for Winforms, too)? For example, is there an event for when Environment.Exit() is called (console app)?
I found a mention of an Exited event in System.Diagnostic.Process, but this appears to be for monitoring the exit of another process, and it does not appear to be received by a process about itself (for example, Process.GetCurrentProcess().Exited += Process_Exited; Process.GetCurrentProcess().EnableRaisingEvents = true;). I would think it might only be raised after the process has actually exited, so that wouldn't work.
This is particularly for .NET 2.0 and C#.
We finally found more about this (but by then my machine had been rebuilt and lost the cookies to my unregistered profile here; hopefully, it will let met post this answer).
Further investigation eventually found a few more events which we have found helpful:
System.Windows.Forms.Application.ThreadExit - Fires when a message loop exits
System.Windows.Forms.Application.ApplicationExit - Fires when all message loops exit
System.AppDomain.CurrentDomain.DomainUnload - Fires when a domain other than the default exits
System.AppDomain.CurrentDomain.ProcessExit - Fires when the default app domain exits
System.AppDomain.CurrentDomain.UnhandledException - Fires when an uncaught exception occurs, ending the app.
Only one of the DomainUnload or ProcessExit events are possible for a given app domain, depending on whether it is the default (top-level) domain for the process or was created as a subdomain (eg. on a web server). If an application doesn't know which it might be (as in our case), it needs to subscribe to both if it wants to catch the actual unload for itself. Also, it appears that UnhandledException (which as of .NET2.0 is always fatal) may prevent the other two events, so that may be a third case to handle. These three events should work for any .NET application.
There is a caveat that the execution time for ProcessExit is bounded (about 4 seconds?), so it may not be possible to do extensive "final" work in that event handler. It needs to be something which can be done quickly.
The Application events only apply to WinForms applications (we suspect they may not apply in pure WPF applications, however). The naming can be misleading because they are named for their most basic normal usage which has certain assumptions. ThreadExit does not relate to the actual System.Threading.Thread but rather to the message loop (Application.Run())) of a UI thread, and ApplicationExit similarly relates to the collection of application Forms on one or more UI threads. Normally, once the call to Application.Run() returns, called from the entry method of a thread, the entry method quickly concludes and the thread itself then ends. And once all UI threads have exited, a WinForms app is usually all done and exits.
Another event of note is the System.Windows.Forms.Application.ThreadException event. A Windows message loop can be configured to catch exceptions which occur in handling a message and send this event rather than let them be uncaught (and thus fatal) exceptions. Catching these exceptions allows the message loop (and that UI thread) to continue running (after aborting the current message handler). There can be only one subscriber to this event at any time for a given thread (subscriptions overwrite any previous subscriber), and it must be configured before any Form is created and subscribed before entering the message loop. See the MSDN help for this event and System.Windows.Forms.Applicaton.SetUnhandledExceptionMode() for more info.