两个DispatchSourceTimers共享一个资源错误多线程任务

时间:2020-11-04 14:25:25

标签: ios swift multithreading

我必须完成一个简单的任务-具有两个按钮和三个踏板的Singleview应用-

开始按钮:

创建线程T1-每3.0秒重复收集一次设备的GPS位置,然后将结果(作为字符串)移交给T3。

创建线程T2-每B秒重复收集一次设备电池的使用百分比,并将结果(作为字符串)移交给T3。

T1和T2中的数据应存储在位置有限(maxData)的数组中。 在线程T3中,如果数组达到maxData,则应通过HTTP将数据发送到服务器(URL)。然后清除数组

停止按钮-只需停止所有三个线程

我对iOS线程一无所知。不幸的是,即使没有必要,App也必须使用线程。在我的previous question中,Rob Napier建议使用DispatchSourceTimers。

我已经接近找到合适的解决方案,但是……仍然是错误的。当我清除数组并发布时,来自DispatchSourceTimer 的单个数据丢失了。我猜想 concurrentDataQueue.async(flags:.barrier)是错误的,我不得不以某种方式阻止读取数组(?)

BackgroundThreadTimer类只是DispatchSourceTimers的包装,该包装取自 medium article(重复计时器)

//partly Pseudocode
var counter = 0
var data = [String]()
var maxData = 5
var counterInt = 0

var concurrentDataQueue = DispatchQueue(label: "dataCleanAndPostQueue", attributes: .concurrent)

var timerLocalization = BackgroundThreadTimer(timeInterval: 2)
timerLocalization.eventHandler = {
    //do sth and receive String x with actual localization
    //...
    concurrentDataQueue.async(flags: .barrier) {
        appendAndPost(phoneInfo: String(counterInt) + ": " + x)
        counterInt += 1
    }
    
}

var timerBattery = BackgroundThreadTimer(timeInterval: 3)
timerBattery.eventHandler = {
    //do sth and receive String x with actual battery level
    //...
    concurrentDataQueue.async(flags: .barrier) {
        appendAndPost(phoneInfo: String(counterInt) + ": " + x)
        counterInt += 1
    }
    
}

func appendAndPost(phoneInfo: String) {
    if data.count < maxData {
        data.append(phoneInfo)
    } else {
        let arrayString = data.joined(separator: "; ")
        DispatchQueue.global(qos: .background).async {
            //post arrayString to http
            print(arrayString)
        }
        data = [String]()
    }
}

//when start pressed
timerLocalization.resume()
timerBattery.resume()

//when stop pressed
timerLocalization.suspend()
timerBattery.suspend()

某人可以帮忙吗?是我的 诊断正确吗?以及解决方法。

1 个答案:

答案 0 :(得分:1)

appendAndPost中,仅当计数小于maxData时才追加结果。

但是,让我们想象一下,如果您在数组中已经有五个项目的地方调用了这个函数。在这种情况下,您可以启动请求,但是您永远不会使用提供的值做任何事情。

我建议无论如何都附加值,并在count达到阈值时发送:

func appendAndPost(phoneInfo: String) {
    data.append(phoneInfo)

    if data.count >= maxData {
        // create your request and send it

        ...

        // reset `data`

        data = []
    }
}
相关问题