two DispatchSourceTimers sharing one resource error, multithread task

青春壹個敷衍的年華 提交于 2021-01-29 07:41:55

问题


I have to make a simple task - singleview app with two buttons and three treads -

Start Button :

create a thread T1 - the GPS location of the device is collected repeatedly every 3.0 seconds, and the results (as a string) are handed over to T3.

create w thread T2 - the percentage usage of the device's battery is collected repeatedly every B seconds, and the results (as a string) are handed over to T3.

Data from T1 and T2 should be stored in array with limited positions (maxData). In Thread T3, if array reaches maxData data should be send to the server (URL) via HTTP. Then clear array

STOP button - just stop all three threads

I am a total noob in iOS threading. Unfortunately, App MUST use threads even if it is not necessary. In my previous question, Rob Napier suggested to use DispatchSourceTimers.

I'm close to find a proper solution, but sth is still wrong. When i clear array and post, single data from DispatchSourceTimer is LOST. I guess, that sth is wrong with concurrentDataQueue.async(flags: .barrier), and i have to block reading of array somehow (?)

Class BackgroundThreadTimer is just wrapper for DispatchSourceTimers taken from medium article(RepeatingTimer)

//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()

Could sb help? Is my diagnosis proper? And how to fix this.


回答1:


In appendAndPost, you are appending result only if the count is less than maxData.

But let’s imagine that you called this where you already had five items in the array. In that scenario, you start the request, but you’re never doing anything with the supplied value.

I would advise appending the value regardless, and sending if the count hits the threshold:

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

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

        ...

        // reset `data`

        data = []
    }
}


来源:https://stackoverflow.com/questions/64670183/multithread-task-threads-in-viewcontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!