|
-
Jan 17th, 2024, 04:36 AM
#1
Thread Starter
New Member
Backgroundworker query
I have an application which has a primary thread with 3 forms open.
I have a fourth form which runs a backgroundworker which is taking data from a telnet session where data is randomly arriving. This form contains a datagridview and I have created a delegate which analyses the incoming data & adds to the datagridview.
All the above are working fine.
One of the other 3 forms contains a datagridview which I need to scan its contents (which are static) & potentially update a cells background colour. I need to call this from within the backgroundworker. The form has a public sub which I am trying to call and pass 2 strings from within the backgroundworker. This is the part I cannot get to work.
Any help appreciated (I am still getting my head around this delegate stuff).
Thanks
Clive
-
Jan 17th, 2024, 08:27 PM
#2
Re: Backgroundworker query
 Originally Posted by g4naq
I need to call this from within the backgroundworker.
You are never "within the backgroundworker". Presumably, you mean from within the BackgroundWorker's DoWork eevnt handler, which is part of the form, not the BackgroundWorker.
Assuming that's true, that code will be executing on a secondary thread so, if you want to interact with a control, you're going to need to marshal a call to the UI thread at some point. You have two choices:
1. You can call a method of the other form from within the DoWork event handler and then the other form can marshal to the UI thread.
2. You can marshal to the UI thread first, then call a method of the other form from there.
Based on the little information you've provided, I'd probably suggest the second option, so you keep all the multi-threading stuff in the one form.
-
Jan 17th, 2024, 09:03 PM
#3
Re: Backgroundworker query
If you're using a BackgroundWorker then you shouldn't really be invoking delegates. The whole reason the BackgroundWorker exists is to avoid that. It's not wrong per se but, if you're going to do it, you may as well not use a BackgroundWorker in the first place. The idea is that you call methods and handle events, which even the biggest newbie has done before. You call RunWorkerAsync and handle DoWork. If you want to interact with the UI during the background work, you call ReportProgress and handle ProgressChanged. If you want to interact with the UI after the background work, you handle RunWorkerCompleted. That's really all there is to it. You can pass data from RunWorkerAsync to DoWork, from DoWork through ReportProgress to ProgressChanged and from DoWork to RunWorkerCompleted.
In your case, what you probably ought to be doing is calling ReportProgress and passing the required data, then handling ProgressChanged and interacting with the other form from there. What that interaction should be actually depends on the relationship between the forms. It may be that you should be calling a method of the other form directly, or it might be that you should be raising an event for the other form to handle. It depends which one opened the other.
-
Jan 18th, 2024, 03:30 AM
#4
Thread Starter
New Member
Re: Backgroundworker query
Thanks for your response. I used a backgroundworker as I had no success using other approaches to dealing with the incoming telnet data without causing what I suspect is some form of blocking.
If you can suggest a better way of dealing with the telnet session data I will rewrite it as I would prefer another approach. Meanwhile I will look at how to use your suggestions.
-
Jan 18th, 2024, 09:20 AM
#5
Re: Backgroundworker query
I would say that other approaches would only make sense if the telnet data has nothing to do with a form. That's probably not a good description. If you can picture the program as being two parts, one being all the forms and everything the user interacts with, while the other part is the telnet part, then if the telnet part can keep running steadily while all the forms are doing whatever they are doing, then there might be a better approach. If the telnet part is launched by some action in a form, and is only running while that form is meaningful, then the backgroundworker approach is probably best.
Either way is possible. What is best comes down to whether the telnet part makes sense as a part of form X, or makes more sense as being separate from all the forms. If it only makes sense as part of form X, then ReportProgress is the way I'd be going about it. That does kind of require that there be a loop, however vague, because you'd be wanting to report progress periodically, but telnet could well have something like a loop. If you get all your data in one giant whack, then there would be no point at which to report progress, which would be a problem. The background would complete before ever having an opportunity to alert the foreground to update itself. With telnet, you are likely doing something more like: Get data, report progress, get more data, report progress, etc. That would work well as either a background worker or as a stand alone thread, and the only difference between the two is whether they make sense as part of a form or not.
My usual boring signature: Nothing
 
-
Jan 18th, 2024, 09:45 PM
#6
Re: Backgroundworker query
Further to what Shaggy said, if it makes sense that the telnet code not be part of a form, you could define a class that did all the telnet work and raised events at appropriate times. One or multiple forms could then create instances of that class and handle those events. You could have the events raised on the UI thread, in which case you'd want to use the SynchronizationContext class to manage that, or you could have the events raised on a secondary thread and the form could be responsible for marshalling back to the UI thread. .NET has a number of classes that raise events on secondary threads and some that give you the option of either. Those that allow either usually have a SynchronizingObject property that you can assign a form or control to and then they will call Invoke or BeginInvoke on that internally to do the marshalling. Examples include the FileSystemWatcher class and the System.Timers.Timer class.
-
Jan 19th, 2024, 03:53 AM
#7
Thread Starter
New Member
Re: Backgroundworker query
Thanks for the suggestions.. my knowledge on some of the options you mention is near zero at present...
The software is for Ham Radio and the main form is a logbook (datagridview), a 2nd form for adding entries manually to the logbook and a 3rd form provides a read-only matrix/map..
The Telnet form (another datagridview) & associated backgroundworker is invoked from the menu bar of the main form and taking a feed of radio stations heard... Data is arriving with quite regularly and needs to be split/dealt with as typically equates to adding multiple rows to the grid.
I need several interactions from the Telnet data.
1) add rows to the datagridview working which I have used the delegate to do a row.insert (appears to work correctly)
2) double click a row to populate the manual entry form (works fine).
3) when data is received from the Telnet session check whether I need to update the 3rd form/matrix to highlight a square (change background colour) based on the data.. This is where I am asking for help.
4) Update another form (which I have yet to create) which provides a subset (sorted) list of the data in the Telnet datagridview
I have not used progress changed until now. I created a class to use with progress changed & added the row to the datagridview here. This has meant I have removed the delagate. I hope this approach is better?
Clive
Last edited by g4naq; Jan 19th, 2024 at 11:39 AM.
-
Jan 19th, 2024, 12:14 PM
#8
Re: Backgroundworker query
 Originally Posted by g4naq
Thanks for the suggestions.. my knowledge on some of the options you mention is near zero at present...
We all start there.
The software is for Ham Radio and the main form is a logbook (datagridview), a 2nd form for adding entries manually to the logbook and a 3rd form provides a read-only matrix/map..
The Telnet form (another datagridview) & associated backgroundworker is invoked from the menu bar of the main form and taking a feed of radio stations heard... Data is arriving with quite regularly and needs to be split/dealt with as typically equates to adding multiple rows to the grid.
I need several interactions from the Telnet data.
1) add rows to the datagridview working which I have used the delegate to do a row.insert (appears to work correctly)
2) double click a row to populate the manual entry form (works fine).
3) when data is received from the Telnet session check whether I need to update the 3rd form/matrix to highlight a square (change background colour) based on the data.. This is where I am asking for help.
4) Update another form (which I have yet to create) which provides a subset (sorted) list of the data in the Telnet datagridview
I have not used progress changed until now. I created a class to use with progress changed & added the row to the datagridview here. This has meant I have removed the delagate. I hope this approach is better?
Clive
That's quite a good project.
What I would suggest would be that you think a bit more about the telnet and the DGV that you are filling from that. Specifically, I would suggest that you separate out the receiving and processing of the telnet data from EVERYTHING else. One thread (and I would tend to use a Thread for this) would be getting the telnet data and putting it into something, but not into a control, or something that can be displayed. If there are multiple columns, I'd be putting the data into a datatable. That's all I'd be having the thread doing...well, that and raising some events.
As to the events, I'd want to raise them on the UI thread periodically. Figuring out when is something that you'd have a better feel for. Are there pauses in the telnet data that would make reasonable times to update the UI? To be reasonable, the pauses would have to be identifiable. If there aren't good pauses, then perhaps there could be a timer, as JMC suggested, that raised a tick event on its own thread, periodically. The updates to the UI could happen on the timer ticks. This would mean that the UI would only be updated every so often, but you could make the timer interval fast enough that the result would be acceptable to the user.
One thing I would be inclined to do for the UI would be to clone the datatable. Basically, I'd have one that the telnet thread would be updating as data arrived, and perhaps that would be cloned periodically such that the UI thread could work with the clone. I'm not sure this would work, but it would mean that the UI wouldn't need to worry about the datatable changing while it was doing work, especially if the datatable was only cloned once every couple seconds. Even once a second would likely be fine. That design would mean that the visible data would tend to be stale, though only by a second or two, which might be acceptable.
That may not be the best approach, either. Getting the data into the datatable is a clear task for the telnet thread. What you then do with the datatable...well, there are lots of options there.
My usual boring signature: Nothing
 
-
Jan 19th, 2024, 01:31 PM
#9
Re: Backgroundworker query
 Originally Posted by Shaggy Hiker
One thing I would be inclined to do for the UI would be to clone the datatable. Basically, I'd have one that the telnet thread would be updating as data arrived, and perhaps that would be cloned periodically such that the UI thread could work with the clone. I'm not sure this would work, but it would mean that the UI wouldn't need to worry about the datatable changing while it was doing work, especially if the datatable was only cloned once every couple seconds. Even once a second would likely be fine. That design would mean that the visible data would tend to be stale, though only by a second or two, which might be acceptable.
I don't think you'd need to clone it. The DataTable could be bound to a DataBindingSource, which would then be bound to the grid. You can then add to the datatable and have it just showup ... if you need to do any processing on the grid, use a timer that ticks off every so often and updates the grid as needed.
-tg
-
Jan 19th, 2024, 02:12 PM
#10
Re: Backgroundworker query
It would be interesting to see the 'telnet' code. Also post a link to the protocol of the data coming from the device.
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|