.NetGrid 2.7.0 has been released. New reporting features

Posted on | February 19, 2012 | No Comments

We have released a new version of .Net Grid! This version contains new reporting features and bug fixes.

.Net Suite, v2.7.0 (Build 2.7.0.46034) [2012-02-20]

Starting from version 2.7.0 grid functionality has been expanded with reporting and printing features. Programmers get simple and convenient interface for implementing new features and can significantly expand capabilities of target applications.

.Net Grid reporting features



Reporting features:

  • Software control of reporting with full customization support.
  • Possibility of adding any images or text to printed pages.
  • Page spanning: If there are too many fields to fit on one page, the fields can span two or more pages.
  • Repeating headers: to improve document readability the grid can insert headers to every printed page.
  • Reports for top-level headers and child headers with relevant content.
  • Hiding headers in reports
  • Repeating selectors: if content has many columns, the grid can span it over multiple pages. This feature can insert row selector to every page.
  • Print preview feature
  • Portrait or landscape page orientation

The following bug has been fixed:

  • [BUG] .Net Grid wrongly filters the content if two filters (Grid.Filter and Column.Filter) are set simultaneously.

Professionals working with complex systems will surely appreciate our efforts that make the code simpler and improve its reliability. Let’s create the best applications together!

Realtime cell highlighting

Posted on | February 15, 2012 | No Comments

Financial markets are lately becoming increasingly volatile and this generates a huge volume of information that has to be displayed in trading applications. Any changes of price or the number of sales/purchase offers for various financial instruments have to be displayed at trader’s screen. Visually it looks as highlighting relevant grid fields for specified time.

Practically any well-designed application should support highlighting of data that changes in real time. However, practical implementation of this feature may be complicated and may significantly impact application performance, thus limiting its usability at high market volatility environment.

In classic implementation of cell highlighting concept the programmer has to store last update time for each grid cell. When cell value changes, the cell should be redrawn with a new color (e.g. when price changes – with green or red background depending on change type). After a certain time interval cell background color should be restored. However, this seemingly simple task is usually hard to implement. Firstly, this depends on data storage method and data volume. If there are too many rows and columns, memory consumption can be fairly high. Secondly, it is necessary to track highlighting time for each cell to restore colors. Some cells may be outside visible area, and this should be considered to save CPU resources. Besides, it is not possible to create high-performance applications without knowing working principles of the painting system and its optimal usages.

Grid grid = ...;
Cell cell = grid.Rows[10]["Bid"];
cell.Highlight(TimeSpan.FromSeconds(2), Color.Blue);

 

.Net Grid uses various optimizations that enable creation of efficient and high-performance applications. The programmer has only to use provided convenient interface and concentrate on application logic.

Dapfor .Net Grid realtime updates

 

The performance of the .Net Grid using various benchmarks demonstrates excellent results. It was really hard work to achieve such high values for various performance indicators. Here are some of them:

  • High insertion rate: 100 000 rows/second.
  • High removal rate: 600 000 rows/second
  • High grouping rate: 60 000 rows/second
  • High real-time regrouping rate: 10 000 rows in a grid of 5 000 rows per second
  • High real-time filtering rate: 7 000 rows in a grid of 5 000 rows per second
  • Productive sort algorithms: 5 000 sorts in a grid of 5 000 rows per second
  • Low memory consumption: The grid of 100 000 rows will consume 16 MB

Professionals working with complex systems will surely appreciate our efforts that make the code simpler and improve its reliability.

Binding list and thread safety

Posted on | February 13, 2012 | 1 Comment

Data binding is the basis of modern applications based on separation of data layer from presentation layer. The main purpose of such separation is to make application logic independent of its representation. Otherwise, logic code should not directly call presentation layer class methods (i.e. Control class methods). When internal state changes, business logic layer sends a GUI notification via IBindingList / INotifyPropertyChanged interfaces and the presentation layer displays modified data on screen.

It is necessary to note that there is a serious obstacle to implementing such event-driven model – thread safety. Business logic shouldn’t know anything of presentation, not only with regard to direct links to GUI classes but also with regard to thread used for subscriber notification. However, in actual applications things are more complicated. Application usually has a single GUI thread where the controls work. All control methods should be called only from this thread. However, data binding doesn’t consider this aspect, i.e. when a data source is connected, most controls imply that all notifications come from the main thread and don’t synchronize. This results in application crashes when notifications arrive from non-GUI thread.

While working with numerous real-world applications we have noted that developers often don’t follow the principle of separating data layer from the presentation layer because it is necessary to synchronize notifications with GUI thread. This means that synchronization is performed by business logic and not by the presentation layer. Thus, the required call of Control.Invoke/Control.BeginInvoke method is placed to business logic that should contain a reference to control that will process notifications.

class FeedCollection : BindingList<Feed>
{
    private Control _control;

    //The method is called when data is updated (for ex. data comes from TCP/IP)
    void OnUpdateReceiced(...)
    {
        _control.Invoke(new MethodInvoker(delegate
        {
            //Raise notification in GUI thread
            OnListChanged(new ListChangedEventArgs(...));
        }));
    }
}

DataGrid someGrid = ...;
FeedCollection feed = ...;
someGrid.DataSource = feed;



It is only one of the examples where rules of separating logic from presentation are violated. When our developers were working on .Net Grid, they have initially designed its architecture to receive notifications from any thread and to perform thread synchronization after that. Thus, business logic can be fully separated from the presentation layer and safely notify subscribers without pre-synchronization of threads and therefore without unnecessary references to GUI controls.

class FeedCollection : BindingList<Feed>
{
    //The method is called when data is updated (for ex. data comes from TCP/IP)
    void OnUpdateReceiced(...)
    {
        //Raise notification directly from non-GUI thread
        //Dapfor .Net Grid will synchronize threads itself.
        OnListChanged(new ListChangedEventArgs(...));
    }
}

Dapfor.Net.Ui.Grid grid = ...;
FeedCollection feed = ...;
grid.DataSource = feed;


As we have said above, ensuring thread safety is not a trivial task for application developers. Complex modern applications may contain a lot of assemblies. Some of them may contain codes with graphical controls, others may contain business logic, various math libraries, code for TCP/IP interaction, etc. However, limitations related to GUI operation only in one thread and thread synchronization method require unneeded and dangerous dependencies of business logic from graphical components (Control.Invoke/Control.BeginInvoke). This may seriously violate the principle of business logic independence from its presentation. Dapfor .Net Grid doesn’t just enable thread synchronization, but also makes it possible to completely avoid such dependencies using an event-driven model. It means that if the application is well architected, business logic assemblies will not (and should not!) depend on Dapfor assemblies and System.Windows.Forms libraries.

Declarative data binding

Posted on | February 9, 2012 | 1 Comment

Component model has two basic interfaces that are broadly used in data binding: INotifyPropertyChanged and IBindingList. The first interface notifies subscribers of bound object modifications while the second one notifies of object collection modifications. Object collections usually don’t contain hierarchy information and they are not intended for this purpose. Different grid developers use different ways to overcome this limitation. Some of them represent IBindingList as a collection containing objects linked by “id – parent id” relations, while the others expand IBindingList syntax adding hierarchy methods to it. We think that both solutions increase code overhead and reduce performance (which is critical for real time applications).

In our opinion, IBindingList should not contain hierarchy information. It is possible to use multiple binding lists to build it. For example, let’s take Strategy class that may contain multiple orders that can be dynamically added to this class or removed from it.

class Order
{
   ...
}

public class Strategy
{
    private readonly BindingList<Order> _orders = new BindingList<Order&gt();

    public IList<Order> Orders
    {
        get { return _orders; }
    }
}

//Add a new order to a strategy:
Order order = ...;
strategy.Orders.Add(order);

//Add a strategy to a grid
Strategy strategy = ...
grid.Rows.Add(strategy);


Let’s note that when a strategy is added to the grid, it cannot display orders as it doesn’t have hierarchy information. It is possible to use declarative binding to tell the grid that Strategy.Orders field should be viewed as hierarchy foundation.

public class Strategy
{
    [HierarchicalField]
    public IList<Order> Orders
    {
        ...
    }
}


When a strategy is added to the grid, it automatically subscribes to binding list returned by this strategy. It enables to use full-featured hierarchical binding with dynamic hierarchy modification without direct access to data presentation layer. To ensure complete separation of presentation layer from data layer we shall place strategy objects to IBindingList:

BindingList<Strategy> strategies = new BindingList<Strategy>();
//Populate collection with strategies
...

//Bind collection to the grid
grid.DataSource = strategies;

----- Strategies and orders will be presented in .Net Grid as following ---------------
+ Strategy
 |- Order
 |- Order
 | ...
+ Strategy
 |- Order
 |- Order
 | ...


Conclusion:
In our example we have achieved full separation of data from presentation. Data manipulation doesn’t require access to control, and this is true for hierarchical declarative data binding as well. Let’s also note that displayed data can be grouped, sorted and filtered without additional effort of the programmer.

In our opinion, the above hierarchy building method is one of the most efficient methods provided by the grid. Besides declarative binding, it is possible to build a hierarchy by simply adding data objects to any row. It is also possible to use conditional binding and binding on any hierarchy level.

Programmers working with actual applications know how much code is required to complete a seemingly simple task of representing hierarchy data in the grid and synchronize it with grid presentation (adding and removing rows, etc). They will definitely appreciate our efforts in this field.

For more information of declarative data binding click here.

Correct organization of event processing in a separate thread

Posted on | December 26, 2011 | No Comments

Multithreaded application became something common. The main reason for that is execution of resource-intensive tasks in parallel to GUI without stopping it for long operations. As it is well known, the easiest way for asynchronous data processing used by ThreadPool. This method is not only the easiest, but also very efficient. Notwithstanding its merits, it has one large backdraw – an application cannot manage ThreadPool lifetime and cannot be confident that during termination ThreadPool doesn’t process previously assigned tasks that may cause application crash.

Let’s review a specific case of threadpool implementation consisting of a single thread. The requirements to this implementation are:

  • Delay between adding task to threadPool and initiation of its execution should be minimal
  • If there are no tasks, threadpool should not consume resources. Specifically, context switches should not be allocated to thread that doesn’t process tasks
  • Threadpool should provide an interface (IDisposable is the best for it) for correct work termination and guarantee that upon Dispose() call, all tasks including tasks in execution shall be completely terminated.
  • Tasks should be executed in sequence without acquiring synchronizing objects.
  • Enable recursive task execution
  • Providing interface for exception handling.

So, there are many requirements and all of those are sufficient. Monitor class is most convenient to implement thread synchronizations. It allows to protect task queue and to move thread to sleep state where it doesn’t consume resources and take it out of this state upon receiving a signal. On adding a new task to the queue and on thread termination request a signal should be sent to this thread. Another useful property of the Monitor is recursive and safe acquiring of the same synchronizing object enabling recursive task addition.

Now let’s review the process of thread pool termination. When a new thread is launched, it is transmitted a method called by the newly created thread. This method usually contains a task processing loop. During execution this cycle constantly checks value of a flag that specifies whether it is necessary to stop task processing. This flag is initially set to false, but Dispose function is set to true. When the calling thread sets this flag to true and notifies the threadpool about it, this thread should wait until threadPool execution ends using Join() method. If threadpool execution doesn’t end in allocated time, the calling thread may be forcibly terminated using Abort().

Exception handling. All task exceptions occur in threadPool thread. Therefore, if it they are not processed, the thread stops. To prevent it, the thread should catch all exceptions occurring during task execution. In a well designed system threadpool should provide interface for notification of extraordinary situation. UnhandledException event is most suitable for this purpose.
As new thread is not launched instantly, to prevent sending tasks to uninitialized thread, it is reasonable to add Monitor to thread start at threadPool.

Now we have just a few things to do – define the interfaces:

public interface ITask
{
    void Execute();
}

public interface IDispatcher
{
    void Dispatch(ITask task);
}

 

An example of ITask implementation enabling use of anonymous methods and lambda expressions for code reduction:

public class Task : ITask
{
    private readonly Action _action;

    public Task(Action action)
    {
        if (action == null)
        {
            throw new ArgumentNullException("action");
        }
        _action = action;
    }
    public void Execute()
    {
        _action();
    }
}

Now comes the hero: a code implementing threadpool based on a single thread:

internal sealed class SingleThreadDispatcher : IDispatcher, IDisposable
{
    private readonly Thread _thread;
    private bool _stopping;
    private readonly Queue _queue = new Queue();
    private readonly object _startSynchro = new object();

    public SingleThreadDispatcher()
    {
        lock (_startSynchro)
        {
            _thread = new Thread(Run) { IsBackground = true };
            _thread.Start();

            //White until the thread is started
            Monitor.Wait(_startSynchro);
        }
    }

    private void Run()
    {
        //Release the calling thread
        lock (_startSynchro)
        {
            Monitor.Pulse(_startSynchro);
        }

        while(true)
        {
            bool exit;
            ITask task = null;
            lock (_queue)
            {
                if (_queue.Count == 0)
                {
                    Monitor.Wait(_queue, 500);
                }
                else
                {
                    task = _queue.Dequeue();
                }

                exit = _stopping && _queue.Count == 0;
            }

            //Execute task without lock
            if (task != null)
            {
                try
                {
                    task.Execute();
                }
                catch (Exception e)
                {
                    if(UnhandledException != null)
                    {
                        UnhandledException(this, new UnhandledExceptionEventArgs(e, false));
                    }
                }
            }

            if(exit)
            {
                break;
            }
        }
    }

    public void Dispatch(ITask task)
    {
        lock (_queue)
        {
            _queue.Enqueue(task);
            Monitor.Pulse(_queue);
        }
    }

    public void Dispose()
    {
        lock (_queue)
        {
            _stopping = true;
            Monitor.Pulse(_queue);
        }

        //Join for a thread and if it doesn't exits, abort it.
        if(!_thread.Join(2000))
        {
            _thread.Abort();
        }
    }

    public event UnhandledExceptionEventHandler UnhandledException;
}

 

Example of initialization:

[STAThread]
static void Main()
{
    using (var t = new SingleThreadDispatcher())
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MyForm());
    }
}

 

Example of use:

t.Dispatch(new Task(()=>
{
    //Some code here
}));

 

Hope this will help you in your dev.
Kind regards,
Dapfor Team

How to avoid exceptions upon exiting application

Posted on | December 23, 2011 | No Comments

Almost every modern application is multi-threaded. Threads are needed to work with various devices and IP protocol stack and to perform demanding computing operations. Results of work performed in these threads should be displayed in graphical controls. Control.Invoke / Control.BeginInvoke are the main methods used for thread synchronization.  These methods work excellent only when control is initialized and contains non-zero wondow handle.

For synchronization programmers often use a Form object that contains controls requiring content update. They probably do it because it’s so easy to implement. It’s so easy to call the following code:

myForm.BeginInvoke(new MethodInvoker(()=>
{
    //a code to be executed in the GUI thread
}), null);

However, simple doesn’t mean correct! GUI thread is not a separate control property but something that is used by all controls. GUI thread lifetime exceeds lifetime of an individual control. Controls and forms can be created or deleted, and all these operations are done via message loop common for all controls and forms. Now let’s say that we started synchronization via myForm.BeginInvoke() upon notification from non-GUI thread. This call adds a window message to message loop. When this message is processed, window handle associated with it is dispatched to specified control or form, and after that a delegate is called. So, what if the form has been closed before that? An exception will be thrown during dispatching. Don’t think that this situation is unusual. When application terminates, it closes windows and performs various actions with end devices, IP stack, etc. These devices in turn may notify GUI of their termination followed by synchronization. This may cause frequent exceptions that are hard to understand and even harder to fix.

We are absolutely convinced that there is only one way out – to create a global dispatcher that is initialized when application starts and is closed when it stops. Dispatcher may be based on the main form launched in Application.Run(). All multi-threaded synchronization should be performed only via this dispatcher. Besides, this approach enables use of other dispatcher for unit tests. As an example we will demonstrate this idea with a code:

 

//Dispatcher class
static class Dispatcher
{
    private static ISynchronizeInvoke _invoker;

    internal static void Init(ISynchronizeInvoke invoker) {_invoker = invoker;}

    public static ISynchronizeInvoke GuiDispatcher { get { return _invoker; }}
}

//How to initialize
using (Form mainForm = new Form())
{
    Dispatcher.Init(mainForm);

    //other initialization code...

    //Start the main loop as usual
    Application.Run(mainForm);
}

//How to use:
Dispatcher.GuiDispatcher.BeginInvoke(new MethodInvoker(()=>
{
    //some code to be executed in the GUI thread
}), null);

 
 

Performance of synchronization with GUI thread

Posted on | December 20, 2011 | No Comments

It is well known that all graphical controls should work in one thread. There are many articles on this subject, so we shall not repeat them. In multi-threaded applications every call should be synchronized with the main thread containing windows message loop. Control is a base class that provides Control.Invoke and Control.BeginInvoke methods. The first of these methods blocks the calling thread until the code contained in delegate is executed. The second method blocks the calling thread only for the time of adding delegate in queue. Execution of this delegate code is done in parallel in GUI thread.

Both Control.Invoke and Control.BeginInvoke methods may accept different delegate types and their parameters. However, this causes a serious performance issue as the main code calling method is Delegate.DynamicInvoke(params object[] args), which in turn uses low-performance reflection. At the same time, for some delegates such as EventHandler, MethodInvoker and WaitCallback the code is called directly. In the time of code execution the delegate is checked for belonging to one of the above types with specified number of parameters, and if it doesn’t – DynamicInvoke() is called.

From practical point of view the synchronization process should look as follows:

    someControl.BeginInvoke(new MethodInvoker(delegate
    {
        //a code here
    }));

 

For comparison, if custom delegates are used, performance of Invoke call from non-GUI thread equals on the average:

Custom delegate: 25,000 calls per second.
MethodInvoker: 40,000 calls per second.

If Control.Invoke is called from GUI thread that doesn’t count inter-thread synchronization rate and doesn’t have context switches, the results are as follows:

Custom delegate: 150,000 calls per second
MethodInvoker:  1,200,000 calls per second.

The example code is provided below:

    ThreadPool.QueueUserWorkItem(delegate
    {
        int k = 0;

        DateTime dt = DateTime.UtcNow;
        for (int i = 0; i < 10000; ++i)
        {
            //CustomDelegate d = delegate { k++; };
            //Invoke(d, new object[]{EventArgs.Empty});

            Invoke(new MethodInvoker(delegate { k++; }));
        }
        TimeSpan ts = DateTime.UtcNow - dt;

        MessageBox.Show(string.Format("{0} invokes. Perf = {1} call/sec", k, 1000*k/ts.TotalMilliseconds));
    });

 

Summary. To improve performance it is always better to use MethodInvoker that improves performance by 50% when calling Control.Invoke method from non-GUI thread and tenfold when calling from GUI thread.

« go back