Good evening all,

This is the first time I have needed to start a new topic, I can usually find the answers via the Google Gods, but not this time – I would very much appreciate your help.

I have written a number of small apps in the past, have come up against this problem before but have managed to fudge it with a simple “refresh” button, but this time, I need the app to refresh the screen automatically (it’s a notification screen for the warehouse operatives).

The app is simple enough. It a simple form that has a number of static objects. One of the objects is a FlowPanelLayout. Within the FPL I create buttons to represent orders waiting to be picked – click on the order(button) and it displays information about the order.

Because this screen is displaying live information, it need to “refresh” automatically. So, to test, I created a refresh button that calls the sub that first deletes all the buttons, then recreates them based on the results of an SQL query – this all works fine.

So, to automate the refresh, I created a timer that called the same sub as the refresh button, I get an error at the bit of code that removes the existing buttons from the FPL:
“Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on.”

So, my questions is, how do I call this sub using the original thread?

I’ve been reading about INVOKE and DELEGATE but it’s not making much sense. I can’t find any examples showing this type of app – windows forms.

This must be quite a common thing – getting an app to refresh it’s data/display.

Thanks in advance for your help


Is really easy to implement.

Assume you want to modify the value of a progress bar, in htis example toolStripProgressBarMain. Direcly assigning the value to the control can result in a cross threading unsafe call. To avoid this

Create a delegate like:

Delegate sub SetProgressDel(percentage as double)

And instantiate it to pint to the right procedure

Public myDelegate = new SetProgressDel(AddressOf setProgress)

Then create a sub that will do the work like:

Public sub SetProgress(percentage as double)
    '   Verify if we are running on the same or distinct thread
    If statusStripMain.InvokeRequired then
        '  We are in a distinct thread so use the invoke instead
            '  Invoke the external thread
            toolStripProgressBarMain.Invoke(myDelegate, new object[] { percentage })
        catch ex as Exception
            msgbox "invoke failed" & ex.Message
            Exit sub
        End try
        '  We are in the original thread, then
        ' Assign the value
        toolStripProgressBarMain.Value = Ctype(percentage, int)
    End If
End Sub

And in your thread safe call, instead of assign the value to the control, call the procedure.

I translated this from c# and this vb is untested, but that's the way.
Hope this helps

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.