KB Article T964838
Visible to All Users

DevExpress WinForms Troubleshooting - Asynchronous Programming

Cheat Sheets, Best Practices and Troubleshooting


Asynchronous programming is a good way to improve your application performance when you request data from a network, access a database, read and write to the file system or perform time-consuming calculations. In this article you will find information on most common issues that may happen in asynchronous code and the ways to resolve them.

Known Issues


Issue 1: An event handler with parameters doesn't work as expected if it uses async/await

Here is a typical implementation of an event handler that demonstrates the issue. In this particular example, we would like to prohibit node expansion in TreeList.

C#
private async void TreeList1_BeforeExpand(object sender, DevExpress.XtraTreeList.BeforeExpandEventArgs e) { e.CanExpand = await GetCanExpandAsync(e.Node.Id); } private Task<bool> GetCanExpandAsync(int nodeID) { return Task.Run(async delegate { await Task.Delay(1000); return false; }); }
Visual Basic
Private Async Sub TreeList1_BeforeExpand(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.BeforeExpandEventArgs) e.CanExpand = Await GetCanExpandAsync(e.Node.Id) End Sub Private Function GetCanExpandAsync(ByVal nodeID As Integer) As Task(Of Boolean) Return Task.Run(Async Function() Await Task.Delay(1000) Return False End Function) End Function

Another typical case is asynchronous validation. For example, you may want to handle the ValidatingEditor event to calculate the validation result asynchronously (set the result to the event's e.Cancel parameter using an async operation).

Cause

This behavior is related to the way asynchronous methods are implemented in .Net. An async event handler (method) runs synchronously until it reaches the first await expression. The event handler is suspended at this position until the awaited task is complete. In the meantime, control returns to the caller of the event handler.
After the task is complete in the background thread, the suspended event handler continues its execution from the await expression. However, a WinForms control has already processed this event. It will ignore event parameters you may set in or after the await expression.
In the example above, the change of the e.CanExpand parameter will be ignored.

Solution

The only solution is to set event parameters using synchronous operations.
You can use the Task<TResult> class to perform an async operation. Use the Task.Result property to obtain the operation's result. Accessing this property is a synchronous operation:

C#
private void TreeList1_BeforeExpand(object sender, DevExpress.XtraTreeList.BeforeExpandEventArgs e) { e.CanExpand = GetCanExpandAsync(e.Node.Id).Result; } private Task<bool> GetCanExpandAsync(int nodeID) { return Task.Run(async delegate { await Task.Delay(1000); return false; }); }
Visual Basic
Private Sub TreeList1_BeforeExpand(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.BeforeExpandEventArgs) e.CanExpand = GetCanExpandAsync(e.Node.Id).Result End Sub Private Function GetCanExpandAsync(ByVal nodeID As Integer) As Task(Of Boolean) Return Task.Run(Async Function() Await Task.Delay(1000) Return False End Function) End Function

Note that waiting for a Task result forces your application to process messages in the app message loop. As a result this approach cannot work in some events like CustomColumnDisplayText because processing messages in the app message loop from this event handler places the control in an inconsistent state.

Issue 2: NullReferenceException in Draw methods of DevExpress controls

Below are examples of methods that you may see in the exception's call stack:

at DevExpress.XtraBars.Ribbon.Drawing.RibbonPainter.Draw(GraphicsCache cache, RibbonViewInfo viewInfo)
at DevExpress.XtraBars.Ribbon.RibbonControl.RibbonPaint(PaintEventArgs e)
at DevExpress.XtraBars.Ribbon.RibbonControl.OnPaint(PaintEventArgs e)
*
at DevExpress.XtraGrid.Views.Grid.Drawing.GridPainter.Draw(ViewDrawArgs ee)
at DevExpress.XtraGrid.Views.Base.BaseView.Draw(GraphicsCache e)
at DevExpress.XtraGrid.Views.Grid.GridView.Draw(GraphicsCache e)
at DevExpress.XtraGrid.GridControl.OnPaintCore(PaintEventArgs e)
*
at DevExpress.XtraTreeList.Painter.TreeListPainter.DoDraw(TreeListViewInfo viewInfo, GraphicsCache cache)
at DevExpress.XtraTreeList.TreeList.OnPaintCore(GraphicsCache cache, PaintEventArgs e)
at DevExpress.XtraTreeList.TreeList.OnPaint(PaintEventArgs e)

When an exception occurs, you often see a red cross painted over the control.

Cause

This exception takes place when the control gets the WM_PAINT message at an inappropriate moment (for instance, when its layout information is being calculated). A typical cause is accessing the control or its elements (columns, rows, data source etc) from a Task or non-UI threads.

Solution

Make sure that you invoke all members of controls or data sources in a synchronous and thread-safe manner. Please refer the How to: Make Thread-Safe Calls to Windows Forms Controls MSDN article to see different thread-safe call techniques.

Additionally, check that you do not perform the following actions in ~CustomDraw event handlers:

  1. Access a database or modify an underlying data source.
  2. Change properties that affect the control's state - modifying settings of the control, its elements (e.g.,columns), RepositoryItems, etc.
  3. Modify the control's filter, sort and group settings.
  4. Invoke the Application.DoEvents method.

See the following article for more information: DevExpress WinForms Best Practices - Update and Load Data from non UI Threads, and Deal with Frequently Updated Data


The issue is not on the Known Issues list:

If the issue you faced is not described above, try doing the following:

  • Check whether the issue occurs with the standard components. For this, add a standard component to your project and try to perform the same operation with this component. If you obtain the same behavior, look for similar issues, errors, and solutions on the web, Stack Overflow.
  • If the issue occurs only when you are using our components, look for a solution in our Search Engine or create a new ticket in our Support Center. Please share as much information as possible (a screenshot, video or project where the issue is reproducible). This information will help us determine the cause of the issue in the fastest and most straightforward way.
Comments (2)

    Hi Stas,
    When using the async/await pattern on an application it will soon grow to the whole code base. At the end you will have async methods that are getting data from the network and affect the UI. The only way to call these methods properly is from a UI async event. These events are usually button clicks but there is also need for : Editor.Validated or Editor.EditValueChanged and Grid.CellValueChanged.
    So my questions are:

    1. Which devexpress editor/grid events are awaited?
    2. Are you planning to support awaited event handlers on these events?
    DevExpress Support Team 3 years ago

      Hello,
      I created a separate ticket on your behalf: T1059659: Which devexpress editor/grid events are awaited?.
      Please refer to it for further discussion.

      Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

      Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.