jfreechart - should adding a point to a dataset be on GUI thread? - jfreechart

When I incoke addition of a data point to a dataset, which is an underlying data set for some chart, by using the code:
timeSeriesCollection.add(time, number);
does this have to be on the GUI thread, or would the updates to the chart, later up the listener chain, convert their updates to be on the GUI thread?

Yes, Swing GUI objects should be constructed and manipulated only on the event dispatch thread. This includes both view and model: ChartPanel (the view) renders your chart in response to events generated by updating your TimeSeriesCollection (the model).

Related

How to make some UI task asynchronously

I have some UI task which took to long. I have some 'home made' property grid ( I uses an ItemControl , where item template uses a ContentControl, the item itself holds the datatemplate to be used in the Content control.).
The application is Shapes viewer, where each shape has its properties. each time the user clicks on some shape, the property grid shows its properties (60 different properties).
The updates process takes something about 1-2 sec. while this updating the application freeze.
Is there any way to do the updating of the property grid in the background?
Is there any way to stop last updating?
Regards, Leon
You should implement the MVVM pattern to make sure that your UI controls is a way to DISPLAY your data rather than be the HOLDER of data.
You can then choose to do various background tasks and only update VM content when ready.
Check out this video:
http://blog.lab49.com/archives/2650
you need to work with thread and dispatcher to do this.
Dispatcher in WPF/SL - http://www.switchonthecode.com/tutorials/working-with-the-wpf-dispatcher
In order to use another thread you have some options:
Threadpool (TaskClass only On .Net 4) - http://msdn.microsoft.com/en-us/library/3dasc8as(v=vs.80).aspx
Thread class - http://msdn.microsoft.com/en-us/library/aa645740(v=vs.71).aspx
BackgroundWorker Class - http://msdn.microsoft.com/en-us/library/cc221403(v=vs.95).aspx
The 3rd option is the easiest if you don't know how to work with threads.
I guess what taking so long is the fetching the properties so what you need to do is to perform the fetch in another thread and then to use Dispatcher in this thread to update your datagrid,
you have to use Dispatcher to update your GUI from another thread.

WPF Multithreading: Using Dispatcher but the UI still hangs?

I am having a bit of a problem with my UI hanging even though I am using a Dispatcher, and before I get any further I'm wondering if it's the way I'm handling the data retrieval.
Right now I have my main window creating a View and ViewModel. Then, inside of a new Thread (using a Dispatcher) it sets the View.DataContext = ViewModel. A very large ObservableCollection is lazily created when the binding kicks in which is causing the slowdown. However, it seems that some of the other UI items that should be showing up before that slowdow don't actually show up.
private void ButtonClick(Object sender, RoutedEventArgs e)
{
MyView view = new MyView();
MyViewModel vm = new MyViewModel();
TabItem tabItem = new TabItem();
tabItem.Header = "MyView";
tabItem.Content = view;
MyTabCollection.Items.Add(tabItem);
Window working = new Working();
working.Show();
ThreadStart thread = delegate()
{
DispatcherOperation operation = Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new Action(delegate()
{
view.DataContext = vm;
((FrameworkElement)view.Parent).Focus();
working.Close();
}
)
);
};
Thread theThread = new Thread(thread);
theThread.Start();
}
This basically says it's supposed to create a view and a viewmodel, then add the view to the tab collection I have (which means it should show the new tab at the least). And, it should also show a "Working..." window. After that, a separate thread is supposed to link the ViewModel to the view, focus on that tab and close the working window. The problem is that the first portion doesn't show until everything is done; The tab is not displayed and the working window is not shown until after the new Thread actually finishes (which causes the Working window to show/close right away). I'm guessing it might have to do with the way I retrieve the data, but I'm not sure. Here is the way it does it:
Create View
Create ViewModel
Create TabItem with Content set to the View and add the TabItem to the TabCollection.
Create/Show the "Working..." window
Dispatcher: Set the View.DataContext = ViewModel. This event sets off the DataBindings, which in turn grab the ObservableCollection. Since the OC is created Lazily it is now being created (this is the bottleneck). <-- Is this messing up my separate thread/dispatcher?
Dispatcher: Set Focus to the tab
Close the "Working..." window
All your extra thread is doing is marshalling another call back to the dispatcher thread. Presumably you actually want to do work on the extra thread, or there's no point in creating it.
Ideally your extra thread should be fetching all the data appropriately, leaving you only to actually connect it all up in the dispatcher thread. The important thing is to decide which work you need to do on the UI thread and which work you need to do on the background thread.
Obviously your analysis of the problem is correct. Your view model is lazily loading data when it is needed, and this is not happening until the Dispatcher callback, at which point you are back on the UI thread again and everything is locked up.
In my opinion, the solution is to do the threading in the data access layer:
For collections: You can define special collections that return only items that have already been loaded from the upstream data source, then trigger loading of additional items on a separate thread when someone subscribes to INotifyCollectionChanged. When the additional items arreive, fire INotifyCollectionChanged events. When INotifyCollectionChanged is unsubscribed, cancel any pending load.
For totals and the like: Same idea. As data comes in the total increases and events occur (automatically for DependencyProperty or using INotifyPropertyChanged).
In addition, the data layer should have a parallel property to each collection, sum, or other delay-loaded value indicating whether it is fully loaded or not, allowing the UI to gray out sections that aren't fully loaded. It is also convenient to have an overall "loading" flag somewhere that can be used to gray out UI sections when anything at all is loading (easier to write the UI this way).
Note that sometimes an operation must block until the actual data has been retrieved. I think the easiest thing in this case is to provide methods in the data layer to force data to be loaded synchronously.
Your DispatcherPriority is set to Normal - try setting it to Background as this may improve the rendering

Creating WPF components in background thread

Im working on a reporting system, a series of DocumentPage are to be created through a DocumentPaginator. These documents include a number of WPF components that are to be instantiated so the paginator includes the correct things when later sent to the XpsDocumentWriter (which in turn is sent to the actual printer).
My problem now is that the DocumentPage instances take quite a while to create (enough for Windows to mark the application as frozen) so I tried to create them in a background thread, which is problematic since WPF expects the attributes on them to be set from the GUI thread. I would also like to have a progress bar showing up, indicating how many pages have been created so far. Thus, it looks like Im trying to get two things to happen in parallell on the GUI.
The problem is hard to explain and Im really not sure how to tackle it. In short:
Create a series of DocumentPage's.
These include WPF components
These are to be created on a background thread, or use some other trick so the application isnt frozen.
After each page is created, a WPF ProgressBar should be updated.
If there is no decent way to do this, alternate solutions and approaches are more than welcome.
You should be able to run the paginator in a background thread as long as the thread is STA.
After you've set up your thread, try this prior to running it.
thread.SetApartmentState(ApartmentState.STA);
If you really must be on the GUI thread, then check out the Freezable class, as you might have to move the objects from your background thread to the GUI thread.
If the portions that require the UI thread are relatively small, you can use the Dispatcher to perform those operations without blocking the UI. There's overhead associated with this, but it may allow the bulk of the calculations to occur in the background and will interleave the work on the UI thread with other UI tasks. You can update the progress bar with the Dispatcher as well.
My guess is that everything that is time-consuming to create is within your Visual. If so, there is an easy solution: Don't create actual DocumentPage objects and their associated Visuals until DocumentPaginator.GetPage() is called.
As long as the code that consumes your document only requests one or two pages at a time there will be no performance bottleneck.
If you're printing to the printer or to a file, everything can be done on a background thread, but if you're displaying onscreen you only need to display a few DocumentPages at a time anyway. In either case you won't get any UI lockups.
The worst case scenario would be an app that displays pages in a thumbnail view. In this case, I would:
The thumbnail view would bind its ItemsSource to a "RealizedPages" collection which initially is filled with dummy pages
Whenever a dummy page is measured, it queues a dispatcher operation at DispatcherPriority.Background to call DocumentPaginator.GetPage() and then replace the dummy page in the RealizedPages collection with the real page.
If there are performance concerns even with realizing a single page because of the number of separate items, this same general approach can be used within whatever ItemsControl on the page has the large number of items.
One more note: The XPS printing system doesn't ever process more than one DocumentPage at a time, so if you know that's your client you can actually just keep returning the same DocumentPage over and over again with appropriate modifications.
Elaborating further on Ray Burns' answer: Couldn't you have your dataprocessing done in a class on a background thread and then databind the DocumentPage's properties to this class when the processing is done?
A little late to the game on this one, but I just worked out a solution to this so I thought I would share. In order to display the UI elements they have to be created on the UI thread on which they will be displayed. Since the long running task is on the UI thread, it will prevent a progress bar from updating. To get around this, I created the progress bar on a new UI thread and created the pages on the main UI thread.
Thread t = new Thread(() =>
{
ProgressDialog pd = new ProgressDialog(context);
pd.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
pd.Show();
System.Windows.Threading.Dispatcher.Run();
});
t.SetApartmentState(ApartmentState.STA);
t.IsBackground = true;
t.Start();
Action(); //we need to execute the action on the main thread so that UI elements created by the action can later be displayed in the main UI
'ProgressDialog' was my own WPF window for displaying progress information.
'context' holds the progress data for my progress dialog. It includes a cancelled property so that I can abort the action running on the main thread. It also includes a complete property so the progress dialog can close when the Action has finished.
'Action' is the method used to create all the UI elements. It monitors the context for the cancel flag and stops generating the UI elements if the flag is set. It sets the complete flag when it is done.
I don't remember the exact reason I had to set Thread 't' to an STA thread and IsBackground to true, but I am pretty sure it won't work without them.

WPF UI Thread Status

I have a wpf application that takes ~30 seconds to create a map/graphic. I have read there is no easy way to tie into the UI rendering thread to get a progress update. So I was going to use a counter on a value converter which colors my map but that is also on the UI Thread, so my question is has anyone found any slick methods of working with the rendering thread yet?
Thanks.
You could create your map/graphic in a BackgroundWorker which allows you to call ReportProgress in your function, where you can set your percentage of completion and raise the ProgressChanged event to update your UI.
When you say UI rendering thread, you mean that hidden rendering thread from WPF internals or UI thread?
In any case, having a separate thread that builds your map and notifies UI about progress doesn't help you?
im not sure if this is what you are looking for.
I use something similar to the code below to load in around 300 images( about 200 mb ) and have no UI slow down at all. (the user can see each image being loaded in, I just keep an empty placeholder image up till the final image is loaded)
The images are loaded in a background thread, and then the function is called to actually put them into the WPF scene.
here is a simple example using a textbox. You can call this function from any thread and it will work out if it needs to change the to the GUI thread. (for my project of course i am doing it with bitmaps, not a textbox ).
delegate void UpdateUIThreadDelegate(String str);
public void DisplayString(String strMessage)
{
if (this.InvokeRequired)
{
UpdateUIThreadDelegate updateDelegate = DisplayString;
this.BeginInvoke(updateDelegate, strMessage);
return;
}
myTextBox.Text = strMessage;
}
Cheers
Anton
If you use binding to tie your UI with a datasource which can take long time to return, you can set 'IsAsync=True' on your binding so that the binding become asynchronous.
If you want to display some other datas (even an animation I guess) during the time your datasource is loading, you can use a PriorityBinding
HTH
Riana

Separate UI thread for details view using WinForms

Our app's master/details view uses a datagridview as the master, and a custom control as the details view. The details view takes a long time to compute and render, making cursoring up/down the master view painfully slow.
Therefore, we'd like the details view to run asynchronously (in a separate UI thread) with change notifications from the master.
Creating a form in a separate thread is relatively straightforward, as Application.Run takes a form parameter.
Is there a way to run a winforms control on a separate thread? I'm aware that native windows in different threads can have a parent/child relationship, just not sure how to set that up using winforms.
TIA,
Updating the UI from a Secondary Thread
http://msdn.microsoft.com/en-us/magazine/cc188732.aspx
Intuitively, you also ought to be able to accomplish the same thing by using a BackgroundWorker. The BackgroundWorker is designed to update UI things like progress bars while executing stuff in the background, and it can be cancelled during its operation.
Is the slowdown caused by the loading of the data, or the population of the UI itself?
Most of the time it's the former, so if that's the case, then the logic that does the data loading should be abstracted into a different thread. The UI code can live in the main thread since updates are quick. You could use either a Thread or a BackgroundWorker in this situation. The key is to separate your data loading from your GUI population.
If you are firing off the update of the detail view in code, you can greatly improve the usability by sleeping 500ms between the time that the user selects the master record, and the time you update the detail view.
This gives the user 1/2 second to scroll to the next record without the details view updating at all.
If you're taking a speed hit during rendering, you should consider suspending layout until the form has completed updating, and then refresh the visible display once at the end.
this.SuspendLayout();
// Do control stuff here
this.ResumeLayout();
If that doesn't help, try this:
[DllImport("user32.dll")]
public static extern bool LockWindowUpdate(IntPtr hWndLock);
//
LockWindowUpdate(this.Handle);
// Do control stuff here
this.Refresh(); //Forces a synchronous redraw of all controls
LockWindowUpdate(IntPtr.Zero);
http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/8a5e5188-2985-4baf-9a0e-b72064ce5aeb

Resources