"The calling thread must be STA, because many UI components require this." Error in WPF? - wpf

I am creating a xps document as below.
Assembly assembly = Assembly.GetExecutingAssembly();
//read embedded xpsDocument file
Stream helpStream = assembly.GetManifestResourceStream(resourceNameOfContext);
if (helpStream != null)
{
Package package = Package.Open(helpStream);
string inMemoryPackageName = "memorystream://" + topicName + ".xps";
Uri packageUri = new Uri(inMemoryPackageName);
//Add package to PackageStore
PackageStore.AddPackage(packageUri, package);
docXps = new XpsDocument(package, CompressionOption.Maximum, inMemoryPackageName);
}
return docXps;
When i am trying to get docXps.GetFixedDocumentSequence();
I am getting the above error. Can anyone help?
Thanks,

Your problem has nothing to do with the code surrounding the creation or use of the XPS document. It has everything to do with what thread you are running under.
You will receive the The calling thread must be STA, because many UI components require this error whenever any of the following are attempted on a MTA thread:
You construct any object derived from FrameworkElement (including Controls and Panels)
You construct any object derived from BitmapEffect
You construct any object derived from TextComposition
You construct any object derived from HwndSource
You access the current InputManager
You access the primary KeyboardDevice, StylusDevice, or TabletDevice
You attempt to change the focus on a FrameworkContentElement
You provide mouse, keyboard or IME input to any control that accepts text input
You make WPF content visible or update its layout
You manipulate the visual tree in such a way as to cause a re-evaluation for rendering
Several other changes, mostly having to do with display and input
For example, I received this error last year when I tried to deserialize some XAML that contained <Button> and other WPF objects from within a WCF service. The problem was simple to solve: I just switch to a STA thread to do the processing.
Obviously most work with XPS documents will trigger one or more of the above conditions. In your case I suspect that GetFixedDocumentSequence ends up using TextComposition or one of its subclasses.
No doubt the my solution of switching to a STA thread will also work for you, but first you need to figure out how your code that works with XpsDocuments is getting executed run from a MTA thread. Normally any code from from the GUI (eg a button press) is automatically run in a STA thread.
Is it possible that your code that manipulates XPS Documents may be being executed without a GUI? From a user-created thread? From a WCF service or a web service? From an ASPX page? Track that down and you'll probably find your solution.
If that doesn't work, let us know the details of the path through which GetFixedDocumentSequence is called, so we can diagnose it. The directly surrounding code isn't nearly as important as the call stack and how it is originally being invoked. If it is hard to explain you probably should add a call stack to prevent misunderstandings and help us diagnose the problem further, or tell you how to start a STA thread in your particular situation.

Is your code trying to access the xps doc from a background thread? If this is the case, you'll want to use the dispatcher. Info on that here.
If this doesn't help, could you post the code where you're actually calling GetFixedDocumentSequence()?

Related

Exception: The Calling thread cannot access this object because a different thread owns it

I'm converting a UI from windows forms to WPF. I'm getting the following exception "The Calling thread cannot access this object because a different thread owns it" whenever I try to call anything on this new WPF window I created.
I referred stack overflow and many websites to find out that I should use Dispatcher.CheckAccess() or somethings similar to dispatcher and check access. I tried many such things
This is one of the things that I have used
Private Delegate Sub ShowSkinInvoked()
If (Dispatcher.CheckAccess()) Then
Me.Show()
Else
Dim d As ShowSkinInvoked = New ShowSkinInvoked(AddressOf ShowSkin)
Dispatcher.Invoke(d)
End If
This has removed the exception and while debugging the error is gone but it freezes the application and I cannot do anything other than terminate it. It doesn't even show the window after "Me.Show".
Also, if I compile the program and then make the calling module use this compiled exe by specifying path to exe then for some reason it works perfect.
If this sounds confusing then what I mean is, I have multiple forms. If I call the code in module A to load and display module B then it gives me the exception but if I call the code in module A to run the compiled exe of module B then it runs perfectly.
Any suggestions?
When WPF creates a user interface it created a thread that is responsible for handling all the user interaction events and scheduling the rendering. This is called the dispatcher thread. Many of the objects that it creates are sub classes of DispatcherObject.
You can't call methods on a DispatcherObject from threads other then the Dispatcher thread that created them. The reasons why are complicated but relate to COM interop.
When you are in a Buttons click event you are running on dispatcher thread.
If you are coming from another thread you must get your work to be performed on the dispatcher thread. It can typically be found by accessing the static current dispatcher Dispatcher.CurrentDispatcher, unless your creating multiple dispatcher threads.
However I would suggest explaining your problem in terms of what work your trying to do with regards to having one form show ui on another. There are multiple ways like an EventAggregator to communicate between ui that might be more appropriate.

Can i recreate a CompositionContainer?

i have a wpf application with login window before displaying the mainwindow.
i use mef to load all modules/parts. before the mainwindow start i check the user login data against the parts which i display then. the parts a Shared and NonShared.
[ImportMany]
private IEnumerable<Lazy<IComponent, IComponentMetadata>> _components;
[ImportMany("Resourcen", typeof(ResourceDictionary))]
private IEnumerable<ResourceDictionary> _importResourcen;
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory));
_mefcontainer = new CompositionContainer(catalog);
_mefcontainer.ComposeParts(somepartwithaSharedExport, this);
this all works fine. but now i tried the "relogin".
_mefcontainer.Dispose();
_mefcontainer = null;
//here the stuff that works from above
first i thought it works, but it seems that the parts i create the first time still exist in memory and i have no chance to "kill" them. so i got OutOfMemory Exception when i relogin enough times.
that why i use this approach now
System.Diagnostics.Process.Start(Application.ResourceAssembly.Location);
App.ShutDown();
i dont feel happy with this.
is there a way to cleanup the Compositioncontainer and create a new one?
You could try to call _mefcontainer.RemovePart(somepartwithaSharedExport). More details here: http://mef.codeplex.com/wikipage?title=Parts%20Lifetime
For the non-shared part you can call CompositionContainer.ReleaseExport:
_mefcontainer.ReleaseExport(nonSharedExport);
For more info have a try the sample code from this answer.
As far as I know, the shared parts cannot be released without disposing the container. If you go with that path, then you will also have to make sure that no references to these objects are kept to allow for the GC to collect them. The documentation reference from mrtig's answer provides a lot of useful details concerning the lifetime of parts and you should probably study it along with the answer by weshaggard to a similar question. It also explains what happens to disposable parts.

WinForms ReportViewer hangs the app WPF

I've been experiencing some problems with the ReportViewer. Basically the code is the following:
public void Display(object dataSource, ReportViewer viewer)
{
currentDs = dataSource as MyTypes;
if (currentDs != null)
{
var param = new LinkedList<ReportParameter>();
param.AddFirst(new ReportParameter("Title", "Title"));
viewer.ProcessingMode = ProcessingMode.Local;
viewer.LocalReport.ReportEmbeddedResource = ReportName;
viewer.LocalReport.EnableExternalImages = true;
viewer.LocalReport.DataSources.Add(new ReportDataSource(DataSourceName + "_Header", currentDs.Header));
viewer.LocalReport.DataSources.Add(new ReportDataSource(DataSourceName + "_Footer", currentDs.Footer));
viewer.LocalReport.DataSources.Add(new ReportDataSource(DataSourceName + "_Lines", currentDs.Lines));
viewer.LocalReport.SetParameters(param);
viewer.RefreshReport();
}
}
The problem is that sometimes it generates the rdlc report but others it just hangs the application. Specifically, it stays in viewer.RefreshReport(); forever.
The corresponding parameters and datasets are correctly set on the rdlc file.
Has anyone experienced a similar behavior?
Thanks in advance.
I suppose you have your viewer configured correctly.
Does the first time generation usually succeed? You could try calling viewer.Reset() after each report generation, that might solve some compounding issues.
There is a post from 2006 that on the surface appears to be relevant and might give you a workaround, although I have to admit I haven't done this myself because it would be almost impossible for me to recreate the problem you're seeing and so it would be equally impossible to see if any workaround would fix it. It's not ideal, but I'm hoping there no such thing as useless information :-)
The relevant info is at the bottom of the linked thread and for the sake of clarity, I've quoted it below.
The ReportViewer control is broken up into two components - the report objects (exposed as .ServerReport and .LocalReport) and the UI (the actual ReportViewer class). The report objects store all of the state about your report. The UI component simply calls into them to get the information it needs to display the report, parameter prompts, toolbar, etc.
The UI component is not thread-safe, just like most controls. But the report objects are thread safe. When you call RefreshReport, the viewer uses a background thread to call Render on the report object. But this is not the only time that the control calls into the report object. The first time it needs to compile the report definition (local report) or create a session (server report) can take a long time. If this "first time" is during RefreshReport, it will happen on the background thread. But as you have seen, it can happen at other times. Populating the parameters UI, for example, requires calling GetParameters, which also requires this startup penalty.
If you want to guarantee this "first time" penalty is on a background thread, then after setting the report path and other connection/data source information, call GetParameters from a background thread.
This seems to suggest that you make some calls to your ReportViewer always from a background thread rather than from the UI thread, so that any delays are not affecting the UI. It sounds like a bit of a bodged design to me though!
Is this of any help to you?
I may have fixed it. This page helped me figure it out: http://ikriv.com/dev/dotnet/MysteriousHang.html
So, it seems that a) report viewer needs to be created on the UI thread, and that b) that wasn't always happening reliably (see link for details). The report viewer is a .NET 2 component, and the behavior documented in the link applies to .NET 2.
To fix it, I employed the following tricks:
first trick: name the UI thread at start up
second trick: force a handle early on, then get a reference to the synchronization context
third trick: use the thread name and sync context to effect the invoke required -> invoke idiom.
If it all holds together, I will come back and post w/ more details.
I encountered the issue in Windows XP with .Net 4.0 and Report Viewer 2010. Yes the OS is end of support but Windows Embedded POSReady 2009 (Windows XP SP3), it's still in the extended support until April 2019.
To workaround the hang, call deprecated API to render the report
rptviewer.LocalReport.ExecuteReportInSandboxAppDomain();
and when exit or rerun the report e.g. report's parameters changed, the report need to clean up properly by
rptviewer.LocalReport.DataSources.Clear();
rptviewer.LocalReport.ReportEmbeddedResource = null;
rptviewer.LocalReport.Dispose();
// release sandbox is required to prevent the lock up, see below note on display report
rptviewer.LocalReport.ReleaseSandboxAppDomain();
// clean up report viewer
rptviewer.Clear();
rptviewer.Reset();
Note on Windows 7, 8, 8.1 and 10. The hang issue is not occurred.

How to get all the AutomationIDs of a WPF application in a file?

In automation of a WPF application (using UI Automation; VSTS 2010), we were adding all the Automation IDs in a Resource File manually and then access it one by one. Considering the application can expand any time, manually adding these IDs can become tedious.
So, is there any tool available which can create this for us? i.e. Get all the ids in a hierarchical format and store it in a file (xml or csv), and then we could parse it whenever required.
I was hoping for a tool like UISpy, which not only can spy all the elements but also export the same.
Do such tools exist? Or is there any alternate approach?
Any valuable feedback is highly appreciated.
Thanks!
I do like this:
public static class AutomationIds
{
public static readonly string MyDataGridId= Create();
private static string Create([CallerMemberName] string name = null)
{
return name;
}
}
<DataGrid AutomationProperties.AutomationId="{x:Static local:AutomationIds.MyDataGridId}"
... />
Then in tests
var dataGrid = window.Get<ListView>(AutomationIds.MyDataGridId);
Assign the automation IDs directly in XAML, then parse XAML files since they are XML after all...
Let's see...
First, I think that your data is not hierarchical - just because a control can be dynamically assigned to be a child of another.
If we change the problem to a subset: "how can we get a hierarchical view of the controls at a time t?" then we can answer this with MS UIA, and say, using a simple RawViewWalker (just a simple breadth-first search on the walker, starting from your main window will do - of course while the application is running so that UIA can reach and query it).
But this subset will not satisfy your initial question, because you'll probably see a portion of your whole ui collection (since some will be hidden / not activated yet at time t).
So it becomes very hard to use a UIA based tool (such as uispy) because then you'll have to set the application view to different states to reach all the controls in your application at different times t1, t2...
I would suggest parsing all your xmls at the same time and build a complete tree of the application's "static" control map, which I believe would be closest to what you're asking for.
Given that this is an old question, I doubt it matters anymore, but just wanted to make the distinctions here.

WPF: how to marshall data to user control from another domain

I have to use functionality that is in another application domain. The result should be displayed in user control.
I have something like that:
var instance = domain.CreateInstanceFromAndUnwrap(...);
instance.Foo(myWpfUserControl as ICallback);
Foo(ICallback itf) {
itf.SetData("...");
}
WpfUserControl.SetData(string data)
{
if (!Dispatcher.CheckAccess())
Dispatcher.Invoke(...)
...
}
I had to put [Serializable] attribute onto WpfUserControll class and implement serialization contructor as well as ISerializable interface but now i receive exception:
The calling thread must be STA because many UI components require this
that is raised from UserControl() constructor
What shall I do to avoid this ?
Thank you in advance !
==============================
Solution
as #Al noticed, my user control have to be serialized when it comes to cross-application-domain calls. Now i pass proxy, that implements ICallback interface. Proxy was marked with Serializable attribute.
Proxy implementation should have absolutely no knowledge about user control as there should be an attempt to deserialize user control instance once again. When I tried to abstract proxy from user control via interface it didn't help. When i tried to pass interface to proxy (that was implemented by user control) - same exception occured.
Finally I decoupled proxy and user control with queue/semaphor. Queue was monitored by a worker thread that deligated calls to user control
p.s. this queue should be inherited from "MarshalByObjectRef".
If the exception is coming from the constructor, it means that you're not creating this control instance from the UI thread. This can be fine but you have to make sure the Thread is an STA thread by calling .SetApartmentState(ApartmentState.STA) on the thread object before the thread is started.
This also means you have to have access to the thread object before its started so you cant do this on a threadpool thread.
The best way to avoid the problem though is probably to create the control on the main UI thread and then assign the Text value using the Dispatcher (or a Task on the UiScheduler). That way you'll also avoid problems if the main thread needs to set, get or bind to the control, as that would cause a cross thread exception if the control was created on another thread
i'd advice against seriealizing the control this way if possible. doing that will generate a new object that is not attatched to any panels or some such, and the original control would not be updated. sadly you cant inheirit from MarshalByRefObject that would eliminate serialization since it would only pass a reference to the other domain.
If you can, call Foo separately and then pass the result to SetData in the original Appdomain

Resources