dispatch_after in swift explanation - swift

I am currently working on a project and for a part of it I need to unhighlight a button after a set period of time. I decided to use dispatch_after.
I have managed to get it working, but can someone please explain me how this line of code exactly works? I have been unable to understand how dispatch_after exactly works.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1000 * Double(NSEC_PER_MSEC))), dispatch_get_main_queue()) {
self.redButton.highlighted = false
}

Let's break it down into multiple statements:
let when = dispatch_time(DISPATCH_TIME_NOW, Int64(1000 * Double(NSEC_PER_MSEC)))
let queue = dispatch_get_main_queue()
dispatch_after(when, queue) {
self.redButton.highlighted = false
}
dispatch_after() enqueues the block for execution at a certain time
on a certain queue. In your case, the queue is the "main queue"
which is "the serial dispatch queue associated with the application’s main thread". All UI elements must be modified on the main thread only.
The when: parameter of dispatch_after() is a dispatch_time_t
which is documented as "a somewhat abstract representation of time".
dispatch_time() is an utility function to compute that time value.
It takes an initial time, in this case DISPATCH_TIME_NOW which
"indicates a time that occurs immediately", and adds an offset which
is specified in nanoseconds:
let when = dispatch_time(DISPATCH_TIME_NOW, Int64(1000 * Double(NSEC_PER_MSEC)))
NSEC_PER_MSEC = 1000000 is the number of nanoseconds per millisecond,
so
Int64(1000 * Double(NSEC_PER_MSEC))
is an offset of 1000*1000000 nanoseconds = 1000 milliseconds = one second.
The explicit type conversions are necessary because Swift does not
implicitly convert between types. Using Double ensures that it
works also in cases like
let when = dispatch_time(DISPATCH_TIME_NOW, Int64(0.3 * Double(NSEC_PER_SEC)))
to specify an offset of 0.3 seconds.
Summary: Your code enqueues a block to be executed on the main
thread in 1000 ms from now.
Update: See How do I write dispatch_after GCD in Swift 3 and 4? for how the syntax changed
in Swift 3.

Related

Causes for EXC_BREAKPOINT crash

I have this stack trace in Crashlytics:
The source code are running is below:
#objc private func playerTimerTick() {
mediaDurationInSeconds = Int32(mediaDuration)
mediaCurrentPositionInSeconds = Int32(currentTimeInSeconds)
if elapsedTimeNeedStoreStartPosition {
elapsedTimeNeedStoreStartPosition = false
elapsedTimeStartPosition = mediaCurrentPositionInSeconds
}
}
The line 1092 is mediaDurationInSeconds = Int32(mediaDuration).
The mediaDuration variable is a Double type and receive a duration in seconds from a AVURLAsset.
This method (playerTimerTick) is running by a Timer.scheduledTimer every 1 second. I have already performed several debugs of this source code and this function and there is no crash. But in the release version is occurring with multiple users and without any explanation.
Has anyone ever had anything like this or do you have any idea what might be causing this crash?

Does setValueAtTime has a specific duration?

In the docs says:
The setValueAtTime() method of the AudioParam interface schedules an instant change to the AudioParam value at a precise time, as measured against AudioContext.currentTime. The new value is given in the value parameter.
From what one can think it makes an instant change but when a run this code
...
biquadNode.gain.setValueAtTime(12, this._AudioContext.currentTime);
console.log("biquadNode.gain " + biquadNode.gain.value);
console.log("biquadNode.frequency " + biquadNode.frequency.value);
setTimeout(() => {
console.log("biquadNode.gain " + biquadNode.gain.value);
console.log("biquadNode.frequency " + biquadNode.frequency.value);
}, 100);
...
It outputs:
0
12
I am not sure why...
It's instant, right, yet asynchronous (and is assumed to be a non-blocking op), as it's executed in a separate thread - note the word schedules in the description. That's why you won't see the change immediately.
Note that another method of updating value, via direct assignment to the corresponding property...
biquadNode.gain.value = 12;
... isn't synchronous either - and is basically equivalent to setValueAtTime(newValue, currentTime), as explained in this issue.

Crontab style scheduling in Play 2.4.x?

Technically I can install cron on the machine and curl the url, but I'm trying to avoid that. Any way to accomplish this?
Reason I want to avoid cron is so I can easily change the schedule or stop it completely without also ssh'ing into the machine to do so.
Take a look at: https://github.com/enragedginger/akka-quartz-scheduler.
Refer to http://quartz-scheduler.org/api/2.1.7/org/quartz/CronExpression.html for valid CronExpressions and examples.
An example taken from the docs:
An example schedule called Every-30-Seconds which, aptly, fires-off every 30 seconds:
akka {
quartz {
schedules {
Every30Seconds {
description = "A cron job that fires off every 30 seconds"
expression = "*/30 * * ? * *"
calendar = "OnlyBusinessHours"
}
}
}
}
You can integrate this into your Play! application (probably in your Global application)
You can use the Akka scheduler.
val scheduler = Akka.system(app).scheduler
scheduler.schedule(0 seconds, 1 hour) {
// run this block every hour
}
The first parameter is a delay, so if you wanted to delay to a specific time you could easily calculate the target time with some simple date arithmetic.
Check out https://github.com/philcali/cronish
Some example code from README.md:
val payroll = task {
println("You have just been paid... Finally!")
}
// Yes... that's how you run it
payroll executes "every last Friday in every month"
val greetings = job (println("Hello there")) describedAs "General Greetings"
// give a delayed start
val delayed = greetings runs "every day at 7:30" in 5.seconds
// give an exact time to start
val exact = greetings runs "every day at noon" starting now + 1.week
// resets a job to its definition
val reseted = exact.reset()
reseted starting now + 1.day

How often can you write to a socket when uploading through FTP?

I'm working on an integrated FTP upload module and using code online I've found this method is called at intervals of 300 milliseconds:
var uploadInterval:int = 300;
var bufferSize:uint = 4096;
private function sendData():void {
var sourceBytes:ByteArray = new ByteArray();
sourceFile.readBytes(sourceBytes, 0, bufferSize);
passiveSocket.writeBytes(sourceBytes, 0, sourceBytes.bytesAvailable);
passiveSocket.flush();
if (sourceFile.bytesAvailable < bufferSize) {
bufferSize = sourceFile.bytesAvailable;
}
}
interval = setInterval(sendData, uploadInterval);
If I set the interval to 5 ms the file uploads in 10 seconds. If I set it 300 ms it loads in around 37 seconds. Is it alright to set it to 5ms instead of 300?
Update:
It looks like there is a commented out command that is using blocking mode. I searched more online and it looks like it's using an interval to be able to get upload progress information. Anyway, here is the original commented out method. I haven't tested it:
private function sendBlockData():void {
var bytes:int;
var sourceBytes:ByteArray = new ByteArray();
sourceFile.readBytes(sourceBytes, bytes, Math.min(bufferSize, sourceFile.bytesAvailable - bytes));
bytes += bufferSize;
bufferSize = Math.min(bufferSize, sourceFile.bytesAvailable - bytes);
passiveSocket.writeBytes(sourceBytes, 0, sourceBytes.bytesAvailable);
passiveSocket.flush();
}
If the socket is blocking, as is usually the default you can write as fast as you can and the write() call will block until the OS can take more data.
So I don't know why the code you found is waiting some milliseconds between write() calls, in the general case you loop and send all your available data without waiting. The OS takes care of blocking the sender when needed.

Replacing Celerybeat with Chronos

How mature is Chronos? Is it a viable alternative to scheduler like celery-beat?
Right now our scheduling implements a periodic "heartbeat" task that checks of "outstanding" events and fires them if they are overdue. We are using python-dateutil's rrule for defining this.
We are looking at alternatives to this approach, and Chronos seems a very attactive alternative: 1) it would mitigate the necessity to use a heartbeat schedule task, 2) it supports RESTful submission of events with ISO8601 format, 3) has a useful interface for management, and 4) it scales.
The crucial requirement is that scheduling needs to be configurable on the fly from the Web Interface. This is why can't use celerybeat's built-in scheduling out of the box.
Are we going to shoot ourselves in the foot by switching over to Chronos?
This SO has solutions to your dynamic periodic task problem. It's not the accepted answer at the moment:
from djcelery.models import PeriodicTask, IntervalSchedule
from datetime import datetime
class TaskScheduler(models.Model):
periodic_task = models.ForeignKey(PeriodicTask)
#staticmethod
def schedule_every(task_name, period, every, args=None, kwargs=None):
""" schedules a task by name every "every" "period". So an example call would be:
TaskScheduler('mycustomtask', 'seconds', 30, [1,2,3])
that would schedule your custom task to run every 30 seconds with the arguments 1 ,2 and 3 passed to the actual task.
"""
permissible_periods = ['days', 'hours', 'minutes', 'seconds']
if period not in permissible_periods:
raise Exception('Invalid period specified')
# create the periodic task and the interval
ptask_name = "%s_%s" % (task_name, datetime.datetime.now()) # create some name for the period task
interval_schedules = IntervalSchedule.objects.filter(period=period, every=every)
if interval_schedules: # just check if interval schedules exist like that already and reuse em
interval_schedule = interval_schedules[0]
else: # create a brand new interval schedule
interval_schedule = IntervalSchedule()
interval_schedule.every = every # should check to make sure this is a positive int
interval_schedule.period = period
interval_schedule.save()
ptask = PeriodicTask(name=ptask_name, task=task_name, interval=interval_schedule)
if args:
ptask.args = args
if kwargs:
ptask.kwargs = kwargs
ptask.save()
return TaskScheduler.objects.create(periodic_task=ptask)
def stop(self):
"""pauses the task"""
ptask = self.periodic_task
ptask.enabled = False
ptask.save()
def start(self):
"""starts the task"""
ptask = self.periodic_task
ptask.enabled = True
ptask.save()
def terminate(self):
self.stop()
ptask = self.periodic_task
self.delete()
ptask.delete()
I haven't used djcelery yet, but it supposedly has an admin interface for dynamic periodic tasks.