Использование таймера Swift в инструменте / демоне командной строки MacOS, который использует Swift-NIO для работы в сети: RunL oop vs wait issue - PullRequest
1 голос
/ 09 июля 2020

Я конвертирую инструмент / демон командной строки Swift MacOS для использования Swift-NIO для работы в сети. Это мой первый проект Swift-NIO.

Инструмент запускает таймер каждые 0,1 секунды. Вот строка внизу main.swift, которая запускает демон / runl oop до преобразования Swift-NIO:

RunLoop.current.run()

Вот таймер в моем классе Universe.swift init () . Всегда существует ровно один экземпляр этого класса:

    timer = Timer(timeInterval: 1.0 / updatesPerSecond, target: self, selector: #selector(timerFired), userInfo: nil, repeats: true)
    timer?.tolerance = 0.3 / updatesPerSecond
    debugPrint("Timer initialized")
    if let timer = timer {
        RunLoop.current.add(timer, forMode: RunLoop.Mode.common)
    }

В этой конфигурации таймер срабатывает 10 раз в секунду, как и ожидалось. Но если я получаю какой-либо сетевой ввод, моя библиотека Swift-NIO вылетает из-за того, что его нет в ожидаемом событии l oop.

enter image description here In Swift-NIO, I'm supposed to add a channel.closeFuture.wait() line to the bottom of my main.swift:

// This will never unblock as we don't close the ServerChannel.
try channel.closeFuture.wait()
RunLoop.current.run()

That solves the Swift-NIO crash, but then I never get to my timer RunLoop, so my timer doesn't fire.

How can I use Swift-NIO to receive (and send) network data, while still having a timer running?

If it helps, the full open source for this project is at https://github.com/darrellroot/netrek-server-swift.

1 Ответ

0 голосов
/ 10 июля 2020

Лукаса был прав. Мне не хватало (и не понимало) какого-то важного контекста.

Мой таймер в конечном итоге пытался отправить данные с помощью SwiftNIO вот так:

    if let context = context {
        let buffer = context.channel.allocator.buffer(bytes: data)
        _ = context.channel.writeAndFlush(buffer)
    }

Исправление заключалось в «отправке» отправки трафик c к контекстному EventL oop:

    if let context = context {
        context.eventLoop.execute {
                let buffer = context.channel.allocator.buffer(bytes: data)
                _ = context.channel.writeAndFlush(buffer)
        }
    }

Он очень похож на DispatchQueue.main.asyn c {} для обновления GUI в iOS приложениях , но с другой терминологией, относящейся к Swift-NIO.

...