I'm developing Windows Phone 8.1 WinRT application (Universal App), which is based on MapControl control.
The problem with it is that, for unknown reasons to me, when I call MapControl.SetLocation() method, I get AccessViolationException. It does not always happen - in fact I've been using that method for quite a long time and everything was fine. But now I'm developing new functionality - it boils down to porting code from MSDN (pushpin clustering) - MSDN Sample. Code contains some callback logic, some async/await usages. The problem is in mentioned earlier SetLocation(). I don't know why it throws exceptions.
What I've tried:
I'm working with MVVMLight, so experimented a lot with DispatcherHelper.CheckBeginInvokeOnUI(). Nothing.
Tried to make sure whether creating the pushpin object happens in UI thread - I don't know how to do that in the debugger (shall I check the tasks windows, or the threads window).
I don't post any code, because, as you can imagine, it's quite a lot of it - and I don't know if that would be any of use. So, my question is, do you know what might cause throwing AccessViolationException when invoking CheckBeginInvokeOnUI? Maybe there are some kind of constraints that I'm not aware of.
Related
I'm someone who solves problems by looking, not asking. So this is new to me. This has been an issue for years, and it crops up with different computers, networks, versions and completely different code. There is a lot here, so, thank you in advance if you are willing to read the whole thing.
Generally speaking, I write MS Access programs that will open Excel and then create multiple worksheets inside of a workbook using data from Access tables and/or Excel sheets. The process can take a couple of minutes to run and occasionally, it will get an error. I could tell you the error message, but it doesn't matter because it will be different depending where the error occurs. When it occurs I simply click debug and click continue and it... continues. If it errors out again (many loops later), it will happen in the exact same spot.
So, what I start with is to make minor changes to the code. In the current program I'm working on, the error happens when I write to a cell and the value is a value directly from a table. I created a variable, copied the value to the variable and then wrote to the cell. The error moved to a completely different part of the program and it became a "paste" error. Generally what fixes it is to put a wait function at the spot where the error occurs. One second is usually good enough. Sometimes it takes a couple of these, but that usually solves it. It only took one delay per loop this time, so it is working. I just hate causing delays in my program. So... Has anyone seen anything like this before, or is it just me. It feels like a timing issue between Access and Excel since the delays are usually helpful. Thanks in advance.
I dug up my last major Access project that interacted with Word (ca. 2016) where I struggled with similar issues. I see many, many Debug.Print statements (some commented, some still active), but unlike what I recalled earlier in my comments, I don't see any "wait" statements anymore! From what I now recall and after re-inspecting the code, most problems were resolved by
implementing robust error handling and best practices for always closing automation objects (and/or releasing the objects if I wanted the instances to persist)
subscribing to and utilizing appropriate automation object events to detect and handle interaction rather than trying to force everything into serialized work-then-wait code. To do this, I placed all automation code in well-structured classes that declared automation objects WithEvents (in VBA of course) and then defined relevant event handlers for actions I was effecting. I now recall finally being able to avoid weird errors and application hangs, etc.
You also may never get a good answer to a question like this, so despite that I am not an absolute expert on Office development, I have had my own experience with frustrating bugs like this and so I'll share my 2 cents. This may not be satisfying, but after experiencing similar behavior using office automation objects, my general understanding is that interaction between OS processes are not deterministic. Especially since VBA generally has no threading or parallelism concerns, it can be strange to deal with objects that behave in unpredictable ways. The time slices given to each process separately is at the mercy of the OS and it will vary greatly with multiple processors/cores, running processes, memory management, etc. Despite the purpose of the automation objects--to control instances of office apps--the API's are not designed well for inter-application processes.
Although it would be great if old automation code would produces more useful errors, perhaps nested exceptions (like in .Net and other modern environments), something that indicates delays and timeouts within callbacks between automation objects, instead you get hodgepodge of various context errors.
My hardware is old, but still ticking. I often get delays, even if only for a second, when switching between apps, etc. Instead of thinking of it as an error, I just perceive it as a slow machine, just wait and continue. It may be useful to consider these type of random errors as similar delays. If a wait call here or there resolves the issue, however annoying, that may just be the best solution... wait and continue.
Every now and then after debugging these types of issues I would actually discover the underlying problem and be able to fix it. At the least I would be able to avoid actual problems with the data, despite errors being raised, just like you describe. But even when I felt that I understood the problem, the answer was still often to do exactly as you have done and just add a short wait.
I do believe now this is a timing issue. After thinking things through, I realized that I could easily (well 3 hours later) separate the database info from the spreadsheet info and then move the updated code that is causing problems into an Excel Macro. I then called that macro from Access. Not only do the errors go away, but it runs about 4 times faster. It's not surprising, I just hadn't thought of that direction before.
I'm looking into Catel. I started following along in the Getting Started for WPF Developers. I create the initial project using the template and run it. All well and good.
Then I take a detailed look at the generated source files. I see references to DataWindow, StyleHelper, and ViewModelBase. And I run in the debugger and watch the Catel debug output, stepping so that I can see when things happen.
And it is all magical.
The view manager somehow runs and registers the MainWindow. And the ViewModelFactory is invoked to create MainWindowViewModel, and the MainWindow DataContext gets set.
How does this all happen? I am missing the documentation that puts together for me the sequence of events when an application starts. I am reluctant to take it on faith, and reluctant to dive into the giant code base without an inkling of where to start. I have read the CodeProject articles and the intro part of the documentation.
Is this driven off of the behaviors some way? How are they invoked? I just can't find the thread that starts me on my way.
Aside: I look at Catel because I found myself implementing a ton of plumbing for a significant MVVM application, and decided that someone else had already solved this problem.
Thanks for any leads. (And thanks, Geert. This is a significant work.)
-reilly.
If I understand correctly, you are looking for advanced information of the inner workings. I think this part of the documentation might be of interest for you.
It might not provide all information you are looking for, but it should provide some.
About some basic questions:
1) The startup windows is defined in App.xaml (that's standard WPF)
2) Since it derives from DataWindow, it uses WindowLogic => LogicBase. The LogicBase uses the IViewModelLocator to find the right view model based on naming conventions (all documented)
3) Then the IViewModelFactory will instantiate the vm (using dependency injection) and return it to the logic which will set it as datacontext.
Note that as the advanced documentation tells you, Catel injects an additional layer to make a difference between the outside datacontext and the VM datacontext (of a window or user control content).
ps. I really recommend starting to use the latest prereleases via NuGet. Catel 4.0 (will be released very soon) is nearly feature complete and will prevent you from a lot of breaking changes that you have to go through (and it is of course much better :-))
http://code.msdn.microsoft.com/office/CppAutomateOutlook-55251528 states:
[...] It is very powerful, but often not recommended because of
reference-counting problems that typically occur when used with the
Microsoft Office applications. [...]
Which reference-counting problems are specifically meant here?
For example, does it apply to the particular example?
Similarly as in the example, I just want to open Outlook, create an appointment, done.
I wanted to use #import but this statements makes me feel afraid about it ...
A circular reference happens when you have two or more objects holding references to each other, directly or indirectly. In COM, it means that circularly linked objects have called IUnknown::AddRef on each other.
In case with Excel automation, that could happen if you connect your event handler (sink) to Excell objects sourcing events (via IConnectionPoint::Advise). This way, you may be keeping a reference to e.g., Application object, while Application object keeps a reference to your sink.
This problem is not specific to smart pointers generated by VC++ #import directive. It's about how you handle the shutdown of the COM objects when you no longer need them. You should explicitly break all connections you've made (i.e., do IConnectionPoint::Unadvise), and call any explicit shutdown API the object may expose (e.g., Workbook::Close or Application::Quit). Then you should explicitly release you reference (e.g, call workbookPtr.Release() on a smart pointer).
That said, if you don't handle any COM events sourced by Excel, you shouldn't be worrying much, the chance you might create a circular reference would be low. Besides, Excel is an out-of-process COM server, and COM has some garbage collection logic in place to manage life-time of out-of-process servers. However, while your application is still open, the Excel process will be kept alive until all references to its object have been released, or Application::Quit has been called.
That is pretty nonsensical. Programming Office interop with the aid of #import is the boilerplate and recommended way. The smart pointer types it auto-generates are explicitly intended to get reference counting done automatically for you so you can't forget to call Release(). There are a few sharp edges, you do have to understand what smart pointers can do and not do.
This is otherwise par for the course for the team that's behind the All-In-One Code Framework. The samples are created by a support team in Shanghai, originally hired to help out in the MSDN forums. These guys don't have the kind of credentials you'd expect from a Microsoft programmer that works in Redmond and their snippets are not being reviewed. Some of them are outright ill conceived. If you ever asked questions at the MSDN forums and saw the answers they post then you know what I mean.
Their Solution2.cpp sample uses late-binding through IDispatch. That's definitely the hard way to interop with Office, you get no help whatsoever when you write the code. IntelliSense is unable to give you any useful information when you write the method call nor can the compiler tell you that you missed an argument or got the argument type wrong. Your program will fail at runtime with an opaque error code, like DISP_E_BADVARTYPE or DISP_E_BADPARAMCOUNT. And the Release() calls have to be made explicitly, that of course makes it easier to miss one. Problems you don't have when you use the smart pointers, they give you auto-completion and type checking. You can see for yourself how much smaller and readable Solution1.cpp is.
Diagnosing a missed call to Release() is otherwise easy, your program completes but you'll still see Outlook.exe running in Task Manager. Something you'll get used to checking anyway, it will also happen when you debug your program, find a bug and stop the program to make a correction. Which of course also prevents Release() from being called so Outlook will keep running. You have to kill it yourself.
Do consider writing this kind of code in a managed language like C# or VB.NET. You'll get a lot more help if you have a problem and you'll find lots of sample code. And the garbage collector never forgets to make a Release call. It is just a bit slow at doing so.
I am not worried about screen real estate. They have changed behavior and added new methods for tablet support. If I call one of these I assume that would cause a run-time failure for the older SDKs. Does this cause me to need a separate tablet version? This is the first time I have had to deal with this on Android and it wasn't clear to me what to do.
Documentation was incorrect and it worked. Don't know why I didn't think of reflection (doh!).
If those methods resides in some classes, which are not the part of pre-honeycomb SDK's you can try to use reflection to get (or not to in case of older devices) a honeycomb's class instance and call it's methods.
If you tell what methods/classes you are trying to use, i can try to make my answer more specific.
I read a lot about how MT works, that it binds to the iOS's API, that it uses AOT compiling, that there is no .NET runtime on the iPhone and so on.
Geoff once wrote this in an answer to one of my questions, which shows how to bind an ObjC selector:
var url = new NSUrl ("http://www.google.com/");
var str = (NSString) Runtime.GetNSObject (Messaging.IntPtr_objc_msgSend_IntPtr (Class.GetHandle ("NSString"), Selector.GetHandle ("stringWithContentsOfURL:"), url.Handle));
But what is happening under the hood if I do this? And does that mean if I use a call that is already bound, it will execute something similar like the code above in the background, hiding it from me? Does it mean that everytime some Selector.GetHandle() and Runtime.GetNSObject() is executed?
How has the whole MT project been started? At some point the team must have been there thinking, "we have ObjC here and Mono there - how can we combine them?" I mean, what was the first thing that was done, tried?
And one last thing about the garbage collector: I assume it has to run in a separate thread - but is it really ONE thred? Or are there several? How does the GC collector decide that it is time to clean up?
Alot of what MonoTouch does is exactly what Mono does on other operating systems.
They started with a subset of the .Net BCL: Silverlight, and also bound the Objective-C apis on the iPhone. They also probably created the AOT compiling option, as I would assume this is the first situation that needed it. Apple required (or strongly preferred) that no one would abstract, or put a layer on top of their APIs. So far MonoTouch, is the only framework that has succesfully done this to bring a new language to the iPhone.
To read some of the more interesting details, check there documentation here. When I first started working with MonoTouch, I read every bullet point under the Documentation heading, as all were pretty interesting and in-depth.
Another resource that you might get more answers than stackoverflow is at their IRC chat. Here is a link to a web-based version, if you don't want to mess with IRC.