LLBLGen blocking my UI thread when I call a MessageBox and also have a databound XtraGrid on my form

Posts   
 
    
scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 09-Sep-2015 11:38:09   

I am experiencing the concurrency issue described here.

http://stackoverflow.com/questions/32473180/why-does-calling-messagebox-show-hang-my-application

I believe it is related to an interaction between my code, LLBLGen and my UI toolkit (DevExpress).

Any advice much appreciated.

scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 09-Sep-2015 11:57:19   

Maybe not concurrency -- I think I'm stuck in some sort of viscous lazy loading cycle with the databinding?

Walaa avatar
Walaa
Support Team
Posts: 14950
Joined: 21-Aug-2005
# Posted on: 10-Sep-2015 07:10:37   

If you have ORM Profiler, please use it, otherwise use sql server profiler to see what queries are executed, or at least enable tracing to see which queries are executed.

You can disable lazyloading by prefetching (using prefetchPaths) related entities.

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 10-Sep-2015 07:11:38   
  • Are you using Adapter or SelfServicing? From your post I guess that your are on SelfServicing.

  • LLBLGen version and runtime library version? (ref...).

  • Does this happen with all your data objects or just with some entity graph? If so, what is the structure of such graph?

Anyway, the first thing to do is to identify where the problem is. For this, I recommend ORM Profiler which was created specially for query performance metrics. It's very useful. From this you can identify what is the kind of 'infinity query' that is performing due to depth lazy loading.

If you don't have or don't want to use ORM Profiler, try to debug the application with sql tracing enabled (See the documentation for more info). Or, at least use some SQL Profiler.

Once the spot is identified let us know the specifics to give you advice on how to eliminate the problem.

David Elizondo | LLBLGen Support Team
scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 11-Sep-2015 01:21:24   

Greeetings,

Sorry for not including additional information.
This is Self-Servicing, LLBLGen 3.5 Final.

This is in a fairly simple database application that makes heavy use of databinding. The problem only occurs when I call MessageBox.Show (perhaps related to the second message pump that creates?)

It's hard for me to identify what object or what structure is causing the problem as the freeze happens in what appears to be this unrelated MessageBox.Show function call. But from PerfView traces, it appears that the MessageBox.Show is sending a WM_PAINT message to it's parent window which contains a UI Control (a DevExpress XtraGrid). The XtraGrid appears to be responding by querying it's DataSource (an LLBLGen collection. PerfView shows a lot of time during the freeze is spent in LLBLGen's SetRelatedEntity.

I setup an ORM Profiler Trial and it shows no DB activity during the "freeze". I also enabled tracing as described in the documentation. During the freeze the only thing I'm seeing in the Output debug window is the time out exception described in this post: http://forums.ormprofiler.com/Messages.aspx?ThreadID=62

UPDATE: So, it looks like there is constant interaction going on between my UI library (DevExpress) and LLBLGen. In fact, the back and forth is dominating one of my logical cores. I think the apparent "freeze" is simply a result of the model dialog launched by the MessageBox.Show event not having time to be painted because the interactions between the two libraries are dominating my message pipe. As a result, the app appears frozen because the modal dialog is preventing interaction--but I can't see the dialog as it hasn't been painted. If I set a breakpoint in the SetRelatedEntity function that is constantly called, here's the stack trace:

>   AcademicStandards.Data.dll!AcademicStandards.Data.EntityClasses.RequestsEntity.SetRelatedEntity(SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore relatedEntity, string fieldName) Line 269  C#
    SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll!SD.LLBLGen.Pro.ORMSupportClasses.EntityCore<SD.LLBLGen.Pro.ORMSupportClasses.IEntityFields>
    .SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore.SetRelatedEntity(SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore relatedEntity, string fieldName) Line 3206  C#
    SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll!SD.LLBLGen.Pro.ORMSupportClasses.EntityCollectionBase<AcademicStandards.Data.EntityClasses.
    RequestsEntity>.PerformSetRelatedEntity(AcademicStandards.Data.EntityClasses.RequestsEntity entity) Line 1474   C#
    SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll!SD.LLBLGen.Pro.ORMSupportClasses.CollectionCore<AcademicStandards.Data.EntityClasses.
    RequestsEntity>.PerformAdd(AcademicStandards.Data.EntityClasses.RequestsEntity item) Line 1299  C#
    SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll!SD.LLBLGen.Pro.ORMSupportClasses.CollectionCore<AcademicStandards.Data.EntityClasses.
    RequestsEntity>.Add(AcademicStandards.Data.EntityClasses.RequestsEntity item) Line 352  C#
    AcademicStandards.Data.dll!AcademicStandards.Data.EntityClasses.DepartmentsEntity.SetRelatedEntity(SD.LLBLGen.Pro.ORMSupportClasses.
    IEntityCore relatedEntity, string fieldName) Line 240   C#
    SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll!SD.LLBLGen.Pro.ORMSupportClasses.EntityCore<SD.LLBLGen.Pro.ORMSupportClasses.IEntityFields>.
    SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore.SetRelatedEntity(SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore relatedEntity, string fieldName) Line 3206   C#
    SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll!SD.LLBLGen.Pro.ORMSupportClasses.EntityCore<SD.LLBLGen.Pro.ORMSupportClasses.IEntityFields>.
    SetSingleRelatedEntityNavigator(SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore toSet, string navigatorNameInRelatedEntity, string navigatorNameInThis, SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore currentValue, bool oppositeNavigatorIsPresent) Line 2520  C#
    AcademicStandards.Data.dll!AcademicStandards.Data.EntityClasses.RequestsEntity.Department.set(AcademicStandards.Data.EntityClasses.
    DepartmentsEntity value) Line 990   C#
    AcademicStandards.Data.dll!AcademicStandards.Data.EntityClasses.RequestsEntity.GetSingleDepartment(bool forceFetch) Line 478    C#
    AcademicStandards.Data.dll!AcademicStandards.Data.EntityClasses.RequestsEntity.Department.get() Line 981    C#
    AcademicStandards.Data.dll!AcademicStandards.Data.EntityClasses.RequestsEntity.DepartmentName.get() Line 1123   C#
    [External Code] 
    [Frames below may be incorrect and/or missing, no symbols loaded for user32.dll]    
    AcademicStandards.exe!AcademicStandards.Program.Main() Line 53  C#
    [External Code] 



daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 11-Sep-2015 07:53:48   

Investigating for this issue, I found your threads at StackOverflow and DevExpress. I will put the links here for reference: http://stackoverflow.com/questions/32473180/why-does-calling-messagebox-show-hang-my-application https://www.devexpress.com/Support/Center/Question/Details/T287807

As there is no DB activity (according to your ORMProfiler trace), the problem is not there. It's something raised in you grid triggered by a form's repaint. The workaround of excluding the parent windows in the MessageBox.Show parameter confirms this.

  • Did you try the Background worker workaround?

  • Does this happen if you use a normal built-in .Net Datagrid?

  • Let us know if you receive any solutions from DevExpress.

David Elizondo | LLBLGen Support Team
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 11-Sep-2015 08:38:05   

I think it could be lazy loading related, if the grid contains references to related entities, which trigger the set related entity simply because the related entity is obtained through lazy loading. The thing is though: that would result in a query and you don't see those

Do you see activity at all in ormprofiler in your app in other places? If you enable dqe tracing on our runtime (see troubleshooting/debugging), do you see activity logged in the vs.net output window if you run your app in debug mode?

Frans Bouma | Lead developer LLBLGen Pro
scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 14-Sep-2015 18:28:08   

Thanks! You are correct. I was able to trace this down to some helper methods on my objects that looked up values in related fields. A simple example (that would have been better handled by using the designer) is for a RequestEntity, there was a custom helper method that looked up the category name of the request, something like: return this.Category.CategoryName

For some reason, calling this helper when there was no related category causes LLBLGen to raise the ListChanged event (even though the data has not been modified). This was not the behavior in prior versions of LLBLGen (this code was recently upgraded to 3.5 and worked fine before the upgrade).

The ListChanged event triggered the DevExpress control to Repaint and we end up stuck in an infinite repaint. Here's a sample stack trace showing it.

Name |+ module System.Windows.Forms.ni <<System.Windows.Forms.ni!BindingSource.ListItem_PropertyChanged>> | + module System.ni <<System.ni!ReflectPropertyDescriptor.OnINotifyPropertyChanged>> | + module <<?!?>> | + module SD.LLBLGen.Pro.ORMSupportClasses.NET20 <<SD.LLBLGen.Pro.ORMSupportClasses.NET20!SD.LLBLGen.Pro.ORMSupportClasses. EntityCore1[System.__Canon].OnPropertyChanged(class System.String)>> | + module AcademicStandards.Data <<AcademicStandards.Data!RequestsEntity.SetRelatedEntity>> | + module SD.LLBLGen.Pro.ORMSupportClasses.NET20 <<SD.LLBLGen.Pro.ORMSupportClasses.NET20!SD.LLBLGen.Pro.ORMSupportClasses. CollectionCore1[System.__Canon].Add(!0)>> | + module AcademicStandards.Data <<AcademicStandards.Data!CategoriesEntity.SetRelatedEntity>> | |+ module SD.LLBLGen.Pro.ORMSupportClasses.NET20 <<SD.LLBLGen.Pro.ORMSupportClasses.NET20!SD.LLBLGen.Pro.ORMSupportClasses. EntityCore`1[System.__Canon].SetSingleRelatedEntityNavigator(class SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore,class System.String,class System.String,class SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore,bool)>> | | + module AcademicStandards.Data <<AcademicStandards.Data!dynamicClass. (class System.Object)>> | | + module DevExpress.Data.v14.2.ni <<DevExpress.Data.v14.2.ni!BaseListSourceDataController.GetRowValue>>

There was no activity showing in the debug traces or the ORM Profiler.

I resolved this issue by using the DevExpressGrid to do the related entity lookups (using it's LookupEditor repository) and got rid of the problematic helper methods on my entity.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39612
Joined: 17-Aug-2003
# Posted on: 15-Sep-2015 09:35:58   

scotru wrote:

Thanks! You are correct. I was able to trace this down to some helper methods on my objects that looked up values in related fields. A simple example (that would have been better handled by using the designer) is for a RequestEntity, there was a custom helper method that looked up the category name of the request, something like: return this.Category.CategoryName

For some reason, calling this helper when there was no related category causes LLBLGen to raise the ListChanged event (even though the data has not been modified). This was not the behavior in prior versions of LLBLGen (this code was recently upgraded to 3.5 and worked fine before the upgrade).

The ListChanged event triggered the DevExpress control to Repaint and we end up stuck in an infinite repaint. Here's a sample stack trace showing it.

Name |+ module System.Windows.Forms.ni <<System.Windows.Forms.ni!BindingSource.ListItem_PropertyChanged>> | + module System.ni <<System.ni!ReflectPropertyDescriptor.OnINotifyPropertyChanged>> | + module <<?!?>> | + module SD.LLBLGen.Pro.ORMSupportClasses.NET20 <<SD.LLBLGen.Pro.ORMSupportClasses.NET20!SD.LLBLGen.Pro.ORMSupportClasses. EntityCore1[System.__Canon].OnPropertyChanged(class System.String)>> | + module AcademicStandards.Data <<AcademicStandards.Data!RequestsEntity.SetRelatedEntity>> | + module SD.LLBLGen.Pro.ORMSupportClasses.NET20 <<SD.LLBLGen.Pro.ORMSupportClasses.NET20!SD.LLBLGen.Pro.ORMSupportClasses. CollectionCore1[System.__Canon].Add(!0)>> | + module AcademicStandards.Data <<AcademicStandards.Data!CategoriesEntity.SetRelatedEntity>> | |+ module SD.LLBLGen.Pro.ORMSupportClasses.NET20 <<SD.LLBLGen.Pro.ORMSupportClasses.NET20!SD.LLBLGen.Pro.ORMSupportClasses. EntityCore`1[System.__Canon].SetSingleRelatedEntityNavigator(class SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore,class System.String,class System.String,class SD.LLBLGen.Pro.ORMSupportClasses.IEntityCore,bool)>> | | + module AcademicStandards.Data <<AcademicStandards.Data!dynamicClass. (class System.Object)>> | | + module DevExpress.Data.v14.2.ni <<DevExpress.Data.v14.2.ni!BaseListSourceDataController.GetRowValue>>

There was no activity showing in the debug traces or the ORM Profiler.

I resolved this issue by using the DevExpressGrid to do the related entity lookups (using it's LookupEditor repository) and got rid of the problematic helper methods on my entity.

Not sure whether list changed events were really changed, I don't recall such a change in v4.x, it might be it did work because of a bug that they didn't work and now they do, but alas, water under the bridge.

What you used to fix it is indeed a much better approach simple_smile Glad it's solved!

Frans Bouma | Lead developer LLBLGen Pro
scotru
User
Posts: 104
Joined: 16-Feb-2006
# Posted on: 15-Sep-2015 23:52:44   

Thanks -- to clarify the version that was working was 2.x and the version where it quit was 3.x (I haven't made it to 4.x yet--I'm always a little behind :-) )

Thanks for your good support.