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.
Related
I wrote a large complex C program around 20(!) years go. As far as I can recall it worked fine at the time in all respects - it was probably running on windows 95.
Now I need to use it again. Unfortunately the radio buttons in it do not appear to work properly any more (the ordinary push buttons are all behaving correctly). As I click on the radio buttons, I get some feedback that windows is acknowledging my click in as much as I see a dotted line appear around the button's text and the circle of the button goes grey for as long as my finger is on the button, but when I take my finger off I see that the selected button has not changed.
My suspicion is that I was perhaps getting away with some bad practice at the time which worked with windows 95 but no longer works on newer versions of windows, but I'm struggling work out what I did wrong. Any ideas?
EDIT: Its difficult to extract the relevant code because the message handling in this program was a tangled nightmare. Many buttons were created programatically at runtime and there were different message loops working when the program was in different modes of operation. The program was a customisable environment for running certain types of experiment. It even had its own built-in interpreted language! So I'm not expecting an answer like "you should have a comma instead of a semicolon at line 47", but perhaps something more like "I observed similar symptoms once in my program and it turned out to be ..... " .. or perhaps "the fact that the dotted rectangle is appearing means that process AAA has happened, but maybe step BBB has gone wrong".
EDIT: I've managed to extract some key code which my contain an error...
char *process_messages_one_at_a_time()
{
MSG msg;
int temp;
temp = PeekMessage(&msg,winh,0,0,PM_NOREMOVE);
if (temp)
{
GetMessage (&msg, NULL, 0, 0);
if (msg.message == WM_LBUTTONUP)
{
mouse_just_released_somewhere = TRUE;
}
TranslateMessage (&msg);
DispatchMessage (&msg);
}
if (button_command_waiting)
{
button_command_waiting = FALSE;
return (button_command_string);
}
else
{
return (NULL);
}
}
There are two simple things to check when using radio buttons. First is to make sure that each has the BS_AUTORADIOBUTTON property set. The second is to make sure that the first button in the tab order and the next control after the set of buttons (typically a group box) have the WS_GROUP property set, while the other buttons have it clear.
A few suggestions:
I'd try to use spy++ to monitor the messages in that dialog box, particularly to and from the radiobutton controls. I wonder if you'll see a BM_SETCHECK that your program is sending (ie, somewhere you're unchecking the button programatically).
Any chance your code ever checks the Windows version number? I've been burned a few times with an == where I should have used a >= to ensure version checking compatibility.
Do you sub-class any controls? I don't remember, but it seems to me there were a few ways sub-classing could go wrong (and the effects weren't immediately noticeable until newer versions of Windows rolled in).
Owner-drawing the control? It's really easy to for the owner-draw to not work with newer Windows GUI styles.
Working with old code like that, the memories come back to me in bits and pieces, rather than a flood, so it usually takes some time before it dawns on me what I was doing back then.
If you just want to get the program running to use it, might I suggest "compatibility mode".
http://www.howtogeek.com/howto/windows-vista/using-windows-vista-compatibility-mode/
However, if you have a larger, expected useful life of the software, you might want to consider rewriting it. Rewriting it is not anywhere near the complexity or work of the initial write because of a few factors:
Developing the requirements of a program is a substantial part of the required work in making a software package (the requirements are already done)
A lot of the code is already written and only parts may need to be slightly refactored in order to be updated
New library components may be more stable alternatives to parts of the existing codebase
You'll learn how to write current applications with current library facilities
You'll have an opportunity to comment or just generally refactor and cleanup the code (thus making it more maintainable for the anticipated, extended life)
The codebase will be more maintainable/compatible going forward for additional changes in both requirements and operating systems (both because it's updated and because you've had the opportunity to re-understand the entire codebase)
Hope that helps...
I'm encountering a performance issue in my application. Essentially I click a button, and a list is populated with databound data (this is virtualized because of the large amount of data), and then click another button which will add a row to an associated list view. I'm being vague because I think it's just necessary to illustrate how little is actually going on in the UI.
Here's what I know:
I don't see the issue on my my beefy dev computer running Win 7 Pro, nor on XP SP3 machines with decent specs. I only see it on a certain brand of laptops (Lenovo ThinkPads) running Win 7 enterprise with 4 GB RAM and Core i5 CPU (much beefier than the XP desktop).
Because of the aforementioned findings, I'm not thinking this is an issue with code.
I profiled with Microsoft's PerfView tool and noticed what I would assume to be an incredibly large number of calls to UIElement.Measure (not ever invoked directly by our code), something I don't see when I profile on the other machines.
The laptop has a 1360x780 resolution, so I thought that perhaps the small resolution was causing the GPU to unnecessarily render the controls because of some data binding that I might be doing (which might explain the large number of calls to Measure()). I extended the laptop's display to my 24" monitor and didn't see any improvement.
Right now I'm assuming that the issue is with the GPU. I've updated the driver with no improvements.
Even though I don't think it's an issue with code, is there a WPF equivalent to "SuspendLayout()"
Is there a way to profile GPU performance to see if it is being hammered during certain processes
(far shot) Has anyone had similar performance issues that seem to be computer specific and suggestions on how to track them down?
Sorry if this is a vague question. I tried to make it comply with SO's usage reqs. Let me know if you want any more info.
Just as an addendum: The program is using WPF, C# 4.0, the issue seems to be around Telerik controls (though I don't think they're suspect since we use them elsewhere without issue).
Turns out it's caused by a known Microsoft issue. I’d try to explain, but I won’t. Mainly because I can’t.
Article talking about fix (see post by Viðar on 3 August 2010):
Microsoft Hotfix site: http://support.microsoft.com/kb/2484841/en-us
Fix: http://archive.msdn.microsoft.com/KB2484841/Release/ProjectReleases.aspx?ReleaseId=5583
1. Answer
To to prevent rampant MeasureOverride calls originating from the WPF ContextLayoutManager:
protected override void OnChildDesiredSizeChanged(UIElement el)
{
/* base.OnChildDesiredSizeChanged(el); */ // avoid rampant remeasuring
}
2. Relevant citation
UIElement.OnChildDesiredSizeChanged(UIElement) Method ...
The OnChildDesiredSizeChanged(UIElement) method has the default implementation of calling InvalidateMeasure() on itself. A typical implementation would be: do whatever optimization your own element supports, and then typically call base OnChildDesiredSizeChanged(UIElement) from a̲t̲ l̲e̲a̲s̲t̲ o̲n̲e̲ of the code branches...
...the implication (and fact-of-the-matter) being that, for any single parent layout pass originated by any one of its children, the parent's MeasureOverride will be called additionally—and likely extraneously—once for each of its children whose size(s) have changed as well.
3. Discussion
In the case where multiple children change their sizes "at the same time", the parent will typically detect and account for the new overall layout amongst all of its children entirely during just the first of these calls. This is standard practice in WPF, and is encouraged by MeasureOverride(…) deliberately excluding any indication of some specific triggering child. Besides the fact that in the most common cases there is no such child (see above link for details), it makes code for attempting any sort of "partial layout" onerous. But mostly, why would any layout calculation ever want to proceed without first obtaining all the very latest available measurements anyway?
So we see that after a single MeasureOverride call, triggered by whichever child happened to be "first" (it shouldn't matter), the layout of the parent should actually be final regarding all of its latest child size information. But this doesn't mean that any queued OnChildDesiredSizeChanged notifications—for other children whose size(s) had also changed—have gone away. Those calls are still pending with the parent, and unless the virtual base call is explicitly abandoned (as shown in bullet #1), each will generate one additional, now-extraneous MeasureOverride call.
4. Caveat
The code shown here disables a̲l̲l̲ child-initiated measure invalidations, which is appropriate for cases where the parent either willfully forbids such changes, or is inherently already aware of them. This is not uncommon; for example, it includes any parent that always fully determines and enforces the size of its children, or more generally, any parent that only adopts DesiredSize values from its children during its own measure pass. What's important is that the measuring of the parent be sufficiently guaranteed by its own parent only.
The situation where a parent might wish to cancel some of the child-initiated measure notifications while preserving/allowing others will naturally depend on additional particular circumstances. It seems more obscure, so it is not addressed here.
When using COM Interop with Office (usually Excel), I always carefully ensure I call Marshal.ReleaseComObject on every reference, to avoid the problem where Excel doesn't quit as described in this KB article.
How can I ensure Excel quits when I use Interop from an OOB Silverlight application (with AutomationFactory.CreateObject)?
Silverlight doesn't have a Marshal.ReleaseComObject method and even calling GC.Collect and GC.WaitForPendingFinalizers doesn't help.
Surely Microsoft hasn't added this feature to Silverlight without a mechanism to release COM references? This seems to me to be a showstopper for automating out-of-process COM servers such as Excel.
A surprising ommission, all the more so as Pete Brown in section 5.5 of his book "Silverlight 4 in Action" goes as far as to say about AutomationFactory.CreateObject, that:
The primary intent of this feature is to allow automation of other applications, including Microsoft Office.
UPDATE in response to Hans' comments.
I'm not convinced the "silent assassin" problem exists in typical automation of Office apps. A common use might look something like the following, which I've seen used repeatedly in WinForms applications without ever coming across the "poisoned RCW" described in the article linked by Hans:
Create an Excel.Application instance
Open or create a workbook
Write data to the workbook
Show Excel if all went well, close the workbook and call Application.Quit if not.
Call Marshal.ReleaseComObject to release all Excel object references.
Failing to call Marshal.ReleaseComObject as recommended by Hans will leave multiple copies of Excel.exe running, as described in the KB article mentioned above - highly undesirable.
UPDATE 2
The sample I'm using to repro this is a sample from the source code for Pete Brown's book Silverlight 4 in action, there's a download link on this page. The sample solution AutomatingExcel is in Ch05.zip / 5.03. To repro:
Make sure no instances of Excel are running
Run AutomatingExcel sample
An Excel workbook is opened
Close Excel
Observe with Task Manager that Excel is still running.
Setting all the dynamic variables to null and calling GC.Collect() seems to work as pointed out in AnthonyWJones's answer.
UPDATE 2
Otaku's answer is what I was looking for - by wrapping references in a using statement the COM references are released without the need to call GC.Collect. A bit of experimentation shows that it's more tolerant of failing to dispose every single reference, unlike the standard Marshal.ReleaseComObject solution described in the KB article referenced above.
It would be interesting to have an authoritative take on exactly what must be disposed to ensure that all Excel references are released.
You could implement the IDisposable interface. The best example of this I've seen is at http://csfun.blog49.fc2.com/blog-entry-79.html. The blog entry is in Japanese, but open in Chrome and let Google do the page translation for you if you don't read Japanese.
Also, if you just want the source code example of the COM wrapper directly you can download the sample app it comes in: SilverOffice.
Take look at this code:-
private void Button_Click(object sender, RoutedEventArgs e)
{
dynamic app = AutomationFactory.CreateObject("Excel.Application");
dynamic book = app.Workbooks.Add();
dynamic sheet = app.ActiveSheet();
sheet = null;
book.Close(false);
book = null;
app.Quit();
app = null;
GC.Collect();
}
The Excel process appears and then disappears. Remove the GC and the Excel process will continue. Do you get the same if you copy this code verbatim? If so then it would suggest that somewhere in your code a reference to an excel object remains reachable from one of the thread stacks or static fields.
Do you ever hold an excel object in a field (as opposed to a local variable)?
Do you hold an excel object in what appears to be variable but is referenced from a dynamic delegate or lambda that is used as an event handler?
Are you attaching event handlers to long-lived objects from an object that has a short lifespan? If so are you ensuring you detach from those handlers properly?
Many of these things can catch devs out into leaving what they think are objects ready for GC but the GC finds them accessible and therefore not candidates for collection.
If the code above doesn't behave the same then we a looking for another issue entirely. I'm using Office 2007 on Server 2008 R2 from the latest SL 4 runtime. However if we are having a varition because of setup then we're on very shakey ground.
Edit
With some testing this appears to be effective:-
private void Button_Click(object sender, RoutedEventArgs e)
{
using (dynamic app = AutomationFactory.CreateObject("Excel.Application"))
{
using (dynamic book = app.Workbooks.Add())
{
using (dynamic sheet = app.ActiveSheet())
{
}
book.Close();
}
app.Quit();
};
GC.Collect();
}
However leave off the GC and you will end up with unwanted Excel processes left running eventually.
I would consider building the Excel file in a WCF service. You can do all the clean up there. Send to bytes to your Silverlight app and use a SaveFileDialog to send them to the user.
Silverlight has a restriction on access to the client file system. Manipulating an Excel file on the client's system, or even assuming the client has Excel installed seems like a violation of this.
by wrapping references in a using statement the COM references are released
Please note: using statements are just syntactic sugar for try/catch/finally with Dispose() in the finally clause.
Also, most applications don't allow for using statements in this case, because creation and cleanup of COM objects are distributed among various places/methods.
The critical line which is needed here reads:
((IDisposable)_excel).Dispose(); // Release COM Interface
This assumes:
dynamic _excel = AutomationFactory.CreateObject("Excel.Application");
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()?
I'm sure there is a good (or at least decent) reason for this. What is it?
I think this is a brilliant question -
and I think there is need of a better
answer.
Surely the only reason is that there
is something in a framework somewhere
that isn't very thread-safe.
That "something" is almost every single instance member on every single control in System.Windows.Forms.
The MSDN documentation for many controls in System.Windows.Forms, if not all of them, say "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe."
This means that instance members such as TextBox.Text {get; set;} are not reentrant.
Making each of those instance members thread safe could introduce a lot of overhead that most applications do not need. Instead the designers of the .Net framework decided, and I think correctly, that the burden of synchronizing access to forms controls from multiple threads should be put on the programmer.
[Edit]
Although this question only asks "why" here is a link to an article that explains "how":
How to: Make Thread-Safe Calls to Windows Forms Controls on MSDN
http://msdn.microsoft.com/en-us/library/ms171728.aspx
Because you can easily end up with a deadlock (among other issues).
For exmaple, your secondary thread could be trying to update the UI control, but the UI control will be waiting for a resource locked by the secondary thread to be released, so both threads end up waiting for each other to finish. As others have commented this situation is not unique to UI code, but is particularly common.
In other languages such as C++ you are free to try and do this (without an exception being thrown as in WinForms), but your application may freeze and stop responding should a deadlock occur.
Incidentally, you can easily tell the UI thread that you want to update a control, just create a delegate, then call the (asynchronous) BeginInvoke method on that control passing it your delegate. E.g.
myControl.BeginInvoke(myControl.UpdateFunction);
This is the equivalent to doing a C++/MFC PostMessage from a worker thread
Although it sounds reasonable Johns answer isn't correct. In fact even when using Invoke you're still not safe not running into dead-lock situations. When dealing with events fired on a background thread using Invoke might even lead to this problem.
The real reason has more to do with race conditions and lays back in ancient Win32 times. I can't explain the details here, the keywords are message pumps, WM_PAINT events and the subtle differences between "SEND" and "POST".
Further information can be found here here and here.
Back in 1.0/1.1 no exception was thrown during debugging, what you got instead was an intermittent run-time hanging scenario. Nice! :)
Therefore with 2.0 they made this scenario throw an exception and quite rightly so.
The actual reason for this is probably (as Adam Haile states) some kind of concurrency/locky issue.
Note that the normal .NET api (such as TextBox.Text = "Hello";) wraps SEND commands (that require immediate action) which can create issues if performed on separate thread from the one that actions the update. Using Invoke/BeginInvoke uses a POST instead which queues the action.
More information on SEND and POST here.
It is so that you don't have two things trying to update the control at the same time. (This could happen if the CPU switches to the other thread in the middle of a write/read)
Same reason you need to use mutexes (or some other synchronization) when accessing shared variables between multiple threads.
Edit:
In other languages such as C++ you are
free to try and do this (without an
exception being thrown as in
WinForms), but you'll end up learning
the hard way!
Ahh yes...I switch between C/C++ and C# and therefore was a little more generic then I should've been, sorry... He is correct, you can do this in C/C++, but it will come back to bite you!
There would also be the need to implement synchronization within update functions that are sensitive to being called simultaneously. Doing this for UI elements would be costly at both application and OS levels, and completely redundant for the vast majority of code.
Some APIs provide a way to change the current thread ownership of a system so you can temporarily (or permanently) update systems from other threads without needing to resort to inter-thread communication.
Hmm I'm not pretty sure but I think that when we have a progress controls like waiting bars, progress bars we can update their values from another thread and everything works great without any glitches.