Updating GridOD on a separate thread

This forum is for programmers who have questions about the source code.
Post Reply
User avatar
wjstarck
Posts: 935
Joined: Tue Jul 31, 2007 7:18 am
Location: Keller, TX
Contact:

Updating GridOD on a separate thread

Post by wjstarck » Tue Oct 20, 2020 7:08 pm

Hello-

I want to update a table on a separate thread regularly using BackgroundWorker so the user will see the updated data refresh every 30 seconds or so and because there can often be a *lot of data to parse so if they wait for a while to push an update button it can take quite a while for all the data to be parsed before it will be displayed.

I had it all working quite nicely, that is until the vScroll_Scroll event fires when a row needs updating, which causes a crash because VScroll is on a different thread, so I get a crossthreading error. Or should I be employing delegation to cross the thread boundaries instead?

Any suggestions?

Error below

Code: Select all

vScroll.Visible=true;
(Line 2868 of GridOD.cs)

Code: Select all

System.InvalidOperationException
  HResult=0x80131509
  Message=Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.
  Source=System.Windows.Forms
  StackTrace:
   at System.Windows.Forms.Control.get_Handle()
   at System.Windows.Forms.Control.SetVisibleCore(Boolean value)
   at System.Windows.Forms.Control.set_Visible(Boolean value)
   at OpenDental.UI.GridOD.LayoutScrollsAndFonts() in C:\Users\wjs\Desktop\ODVersions\opendental20.3\opendental20.3\OpenDentBusiness\UI\GridOD.cs:line 2868
   at OpenDental.UI.GridOD.EndUpdate(Boolean preserveIndices) in C:\Users\wjs\Desktop\ODVersions\opendental20.3\opendental20.3\OpenDentBusiness\UI\GridOD.cs:line 3349
   at Anesthesia.FormAnestheticRecord.FillGridVSData(Int64 anestheticRecordNum, String anestheticDate) in C:\Users\wjs\Desktop\ODVersions\opendental20.3\EASy20.3\Forms\FormAnestheticRecord.cs:line 1225
   at Anesthesia.FormAnestheticRecord.timerVSMStatus_Tick(Object sender, EventArgs e) in C:\Users\wjs\Desktop\ODVersions\opendental20.3\EASy20.3\Forms\FormAnestheticRecord.cs:line 3464
   at Anesthesia.FormAnestheticRecord.<>c__DisplayClass7_0.<FormAnestheticRecord_Load>b__0() in C:\Users\wjs\Desktop\ODVersions\opendental20.3\EASy20.3\Forms\FormAnestheticRecord.cs:line 219
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

  This exception was originally thrown at this call stack:
    [External Code]
    OpenDental.UI.GridOD.LayoutScrollsAndFonts() in GridOD.cs
    OpenDental.UI.GridOD.EndUpdate(bool) in GridOD.cs
    Anesthesia.FormAnestheticRecord.FillGridVSData(long, string) in FormAnestheticRecord.cs
    Anesthesia.FormAnestheticRecord.timerVSMStatus_Tick(object, System.EventArgs) in FormAnestheticRecord.cs
    Anesthesia.FormAnestheticRecord.FormAnestheticRecord_Load.AnonymousMethod__0() in FormAnestheticRecord.cs
    [External Code]
Cheers,

Bill Starck, DDS
Big Idea Software, LLC
Developer, EASy(Electronic Anesthesia System) for Open Dental
817-807-1709
TX, USA

User avatar
jordansparks
Site Admin
Posts: 5739
Joined: Sun Jun 17, 2007 3:59 pm
Location: Salem, Oregon
Contact:

Re: Updating GridOD on a separate thread

Post by jordansparks » Mon Oct 26, 2020 10:25 pm

Glad you asked. Threads with UI is a terrible combination. I have rules against using that combo in our code, and I'm constantly chasing down violations. Any time you think you need a thread, there are a variety of other strategies that will work much better and be bug free. It's hard to understand from your description what you are parsing, so it's hard to give you pointers, but maybe something like this:
1. Timer (Form.Timer, not Thread.Timer) fires every 30 seconds.
2. UI locks up, along with a wait cursor
3. Make changes to the grid
If step 2 takes longer than 2 seconds, use ProgressOD so that the user can hit cancel in the middle. Also, try to optimize it so that it goes faster. If you're just using strings, consider StringBuilder and/or RegularExpressions to speed things up. Nothing should really be that slow.
Jordan Sparks, DMD
http://www.opendental.com

User avatar
wjstarck
Posts: 935
Joined: Tue Jul 31, 2007 7:18 am
Location: Keller, TX
Contact:

Re: Updating GridOD on a separate thread

Post by wjstarck » Thu Oct 29, 2020 7:06 am

Thanks for that.

I figured out that the reason for the long load times (there is a lot of Hl7 data streaming in from a vital sign monitor) is that I was re-processing all the messages every time. By marking an HL7 message as processed once it has been imported to the db, I'm not re-parsing all the messages with every save. So I can just put a FillGrid() inside a timer.

Thanks.
Cheers,

Bill Starck, DDS
Big Idea Software, LLC
Developer, EASy(Electronic Anesthesia System) for Open Dental
817-807-1709
TX, USA

Post Reply