ProgressWheel with Thread and Timer

Hi,
I have a shell command that blocks my progresswheel. I put my Shell command in Thread1.Run() (it’s ok ?) and a Timer.
2 questions:
1/ What should I put in the Timer? (ProgressWheel1.Visible and ProgressWheel1.Enabled ?)
2/ Where stop the ProgressWheel?

In Timer1.Action() I tried this:

if Me.RunMode = Timer.RunModes.Multiple then
  ProgressWheelXPR.Visible = true
  ProgressWheelXPR.Enabled  = true
elseif Me.RunMode = Timer.RunModes.Off then //???
  ProgressWheelXPR.Visible = false
  ProgressWheelXPR.Enabled  = false
end

but the ProgressWheel does not stop at the end of the process !
At the end of Thread1.run() I tried: Timer1.Mode = Timer.ModeOff

If I put the ProgressWheel.enable= false or .visible = false at the end of Thread.Run() I get a ThreadAccessUIException !
Thanks

If the timer is runing…
just keep it runing forever and never turning it off ???
That has no sense at all :upside_down_face:

Shouldnt you be checking if your thread is completed or not? (and turn on or of the timer acording to that)

@Ivan_Tellez
At the end of Thread1.run() I put: “Timer1.Mode = Timer.ModeOff”… to stop the Timer. Otherwise, how do you know if the thread is finished?

If the timer is already off, how exactly can this part can be reached?

A IsFinished variable that can be checked in the timer?

Putting the shell in a thread will make no difference at all to it blocking the UI. The only thing that will make it unblock the UI is to change the mode to Aynchronous.

You then start the Shell command and catch the end of the command in the Completed event. If you are expecting data back from the shell you will get that via the DataAvailable event.

You can add a shell to a window and change the mode and add events to it. Or you can subclass shell and add things there.

1 Like

As far as threads go, you can use the UserInterfaceUpdate event along with the AddUserInterfaceUpdate method to interact with your controls from within a thread.

1 Like

Hello,
Thank you, thanks to your information, I was able to succeed.
I just have an exception when I display an info in a Label:
“A thread attempted to manipulate a UI element. This can only be done from the main application thread.”
I think I need to use App.DoEvents(), I need to see how it works.

Don’t use App.DoEvents. You’ll regret it in the long run. Use the UserInterfaceUpdate mechanism that’s built into threads.

Ok, thanks, but what should I put to display a string in a Label component?
“Thread.AddUserInterfaceUpdate(ParamArray data as Pair)”

Would it give something like this?
Thread1.AddUserInterfaceUpdate(“LabelName” : LabelTextVariable)

Sure, anything you want. The field(s) you provide are given to you in a dictionary when the event is raised so it can be whatever you want.

And you have to add the UserInterfaceUpdate event to the thread where you’ll do the actual work of updating the UI.

A somewhat more straightforward method for simple cases like just updating a progressbar or wheel is to add a timer and a property holding the progress value to your window. Update the property from the thread and in the timer’s Action event assign the property’s value to that of the progressbar/wheel.

It’s maybe less “encapsulated” than the UserInterfaceUpdate method, but easier for beginners to get their head around than parsing an array of dictionaries.

1 Like

Thank you @Julia_Truchsess , but for the wheel, it’s done.
I just have an exception when I display a string in a Label, with the following message:
“A thread attempted to manipulate a UI element. This can only be done from the main application thread.”
Now, it seems to me that it is necessary to use the “UserInterfaceUpdate” event to display the content of my Label without generating an exception in my thread but apparently it also goes through a Dictionary (of which I do not really understand the interest) :
AddUserInterfaceUpdate(data As Dictionary)
or AddUserInterfaceUpdate(ParamArray data As Pair)

For the moment, it seems rather vague to me, I will do a test to see what it gives.

OK, It works well now. Thanks all.

Exactly as expected.

Every time you call AddUserInterfaceUpdate your request for an update is added to an array of dictionaries that is available to you in the event handler I mentioned upthread. The dictionary gives you the most flexible way of passing data to the event handler that you must write to do the actual updating. In my case, each dictionary has an “action” key, whose value drives a select case, and then any other keys for data items needed to do a specific update of the UI.

So the code in the event handler looks like this:

Var  updateItem as new Dictionary

while  (data.LastIndex>-1)
  
  updateItem = data(0)
  data.RemoveAt (0)
  
  select case updateItem.Value("action")
    
  case 1
    // code updating the UI for this action

  case 2
  // etc

...

  end select

wend

If your thread wants to make lots of different changes to the UI, you’ll need a way of passing a variety of parameters into the event handler. The dictionaries provide that.