Threads: Remaining time

Hi everyone,

I read a text file into a project with TextInputStream. For this I use a thread, because these are very large text files. The progress of the import is calculated correctly, so I can output a percentage in the UI. I calculate these from the total size of the file (bytes) and the bytes already read.

But now I want to display an additional value that shows the remaining time in the UI. Are there any ideas or concepts on how to do this?

Thank you!

take the time already elapsed and multiply by the amount of the file read and divide that by the total size of the file

(ET / ByteRead) * (fileSize)

So if 10 seconds have elapsed and you read 8% of the file and the file is 52k

then it is ( 10 / 4160) * 52000) = 125 seconds - 10 = 115 seconds to go

and it self adjusts if the processing slows down or speeds up

In the newest Xojo, use the new event in a Thread.

In previous versions, see the Task example that will do what the new version of Xojo offers.

Don’t use a Thread at all. Instead, use something like my Looper class that leverages a Timer to perform a task in chunks in the main Thread so you can access the UI directly.

https://github.com/ktekinay/Xojo-Looper

Check this out too: https://blog.xojo.com/2019/11/18/updating-the-ui-with-the-new-thread-class/

I love these kinds of updates to Xojo!

Like this?

[code]Var startTime As DateTime = DateTime.Now

Var currentTime As DateTime = DateTime.Now
Var elapsedInterval As DateInterval = currentTime - startTime
Var elapsedTime As New DateTime(elapsedInterval.Year, elapsedInterval.Month, elapsedInterval.Day, elapsedInterval.Hour, elapsedInterval.Minute, elapsedInterval.Second, elapsedInterval.Nanosecond)

// And now, how to go on?

Var time As Integer = (??? / ByteRead) * (fileSize)
[/code]

I already use the new thread features introduced with 2019r2!

Yeah, sorry for the noise, I misread your question.

No problem :wink:

…or should I better use System.Microseconds?

Microseconds or Ticks would be better here, I think.

Var startTime As Integer = System.Ticks Var currentTime As Integer ... currentTime = System.Ticks time = (((currentTime - startTime) / 60) / ByteRead) * fileSize)
This doesn’t look good to me.

I think you need to subtract the already read bytes from the total file size to get seconds left.

time = (((currentTime - startTime) / 60) / ByteRead) * fileSize)

Should Be:

time = ((currentTime - startTime) / 60) / ByteRead) * (fileSize-BytesRead)

In the first half you are calculating how many bytes per second you are reading. I think you have to multiply that by whats left to get remaining time.

Here is a generic method I use to return the progress ‘X of Y (XX time so far, YY remaining)’. It uses a couple of other methods to display a long integer, the percentage, date difference and seconds as time — you can roll your own. I get the start time once then pass it into this method along with the item and total items.

[code]Protected Function getTimeRemainingWAD(upToValue As Integer, totalValues As Integer, timeStarted As Date, showPercentage As Boolean = True , timeRemaining As Boolean = True, timeSoFar As Boolean = True) as String
Dim tempDate As New Date
Dim myString As String
Dim bracketText As String
Dim secondsDifference As Integer
Dim secondsRemaining As Integer

if upToValue > totalValues then upToValue = totalValues 'presumeably a mistake!
if upToValue < 0 or totalValues < 0 or timeStarted = nil or tempDate.TotalSeconds < timeStarted.TotalSeconds then Return “”

secondsDifference = tempDate.TotalSeconds - timeStarted.TotalSeconds 'current time less time started
secondsRemaining = secondsDifference * ((totalValues - upToValue) / upToValue)

myString = commonStrings.getLargeDecimalWAD(upToValue) + " of " + commonStrings.getLargeDecimalWAD(totalValues)

if not showPercentage and not timeRemaining and not timeSoFar then 'don’t bother with the brackets!
Return myString
end if

if showPercentage then
bracketText = bracketText + commonStrings.getNumberAsPercentageWAD(upToValue / totalValues) + ", "
end if

if timeSoFar then
bracketText = bracketText + getDateDifferenceWAD(timeStarted, tempDate, “”, True, True, True) + " so far, "
end if

if timeRemaining then
bracketText = bracketText + getShowTimeWAD(secondsRemaining) + " remaining, "
end if

if right(bracketText, 2) = ", " then bracketText = left(bracketText, len(bracketText) - 2)

myString = myString + " (" + bracketText + “)”

Return myString

End Function
[/code]

Many thanks for the numerous contributions. At the moment I have implemented this with API 2.0 through your input:

Var started As DateTime = DateTime.Now Var timeLeft As DateTime = DateTime.Now Static secondsDifference As Integer ... secondsDifference = DateTime.Now.SecondsFrom1970 - started.SecondsFrom1970 timeLeft = New DateTime(secondsDifference * ((fileSize - bytesReadSoFar) / bytesReadSoFar))
The minute and second values obviously match with the progress indicator, but unfortunately my time output in the label always shows a 1 as the remaining hour value.

// d = DateTime Object PercentageLabel.Value = Format(d.Hour, "00") + ":" + _ Format(d.Minute, "00") + ":" + _ Format(d.Second, "00")
Even after the file has been read, it displays one.

[quote=467730:@Martin Trippensee]Many thanks for the numerous contributions. At the moment I have implemented this with API 2.0 through your input:

Var started As DateTime = DateTime.Now Var timeLeft As DateTime = DateTime.Now Static secondsDifference As Integer ... secondsDifference = DateTime.Now.SecondsFrom1970 - started.SecondsFrom1970 timeLeft = New DateTime(secondsDifference * ((fileSize - bytesReadSoFar) / bytesReadSoFar))
The minute and second values obviously match with the progress indicator, but unfortunately my time output in the label always shows a 1 as the remaining hour value.

// d = DateTime Object PercentageLabel.Value = Format(d.Hour, "00") + ":" + _ Format(d.Minute, "00") + ":" + _ Format(d.Second, "00")
Even after the file has been read, it displays one.
[/quote]

You need to set the timezone after New DateTime( seconds, timezone ) when using the seconds constructor

Unfortunately this is not the puzzle solution, if I specify TimeZone.Current, the one still remains.

Also in DateTime.Now ?
http://documentation.xojo.com/api/data_types/datetime.html#datetime-now

Docs say the default is local timezone. Maybe a bug?

You may be better off using DateInterval for the calculation Dateinterval = (LatestDate - previousdate)

why would the timezone even be relevant here? you are looking at relative time, not clock time… an elapsed hour is the same regardless of the timezone within which it was calculated

Bevause there is 1 hour difference, it seems to be a timezone diff. But it could be anything, best is to use DateInterval.

Could be a xojo bug.

Don’t use Date/DateTime at all. This is best done with Ticks or Microseconds.

Looks like.

Could you please create a small sample for me? I need hours, minutes and seconds as returned result. Thanks.