社区首页 >问答首页 >不应该运行的Swift代码运行两次

不应该运行的Swift代码运行两次
EN

Stack Overflow用户
提问于 2020-11-11 18:05:11
回答 2查看 75关注 0票数 0

我有一个转义函数,它在满足条件后完成:

代码语言:javascript
代码运行次数:0
复制
  private func xxxfastLoadLSecurityDescriptions(session: URLSession, mySymbols: [String]?, completion: @escaping(Bool) ->())    {
        
        var counter = mySymbols?.count ?? 0
        if counter == 0 { completion(false) }
        var doubleCount = 0
        // print("DESCRIPTION Starting Counter = \(counter)")
        
        for symbolIndex in 0..<(mySymbols?.count ?? 0) {
            guard let mySymbol = mySymbols?[symbolIndex] else { print("ERROR in fastLoadLSecurityDescriptions loop: No Symbol") ;  continue }
            guard let myGetDescriptionRequest = GenericDataRequest(dataToSend: [mySymbol], token: sessionToken, mgbRoute: MGBServerRoutes.retrieveSecurityDescriptionsRoute!)
            else { print("Error Getting Security Description Request for \(mySymbol)") ; return }
            
            mySessionSendMGBGenericRequest(session: session, request: myGetDescriptionRequest) { [weak self]  success, serverMessage, returnUNISecurityDescription in
                guard let self = self else { print("ERROR: self is nil") ; return }
                if returnUNISecurityDescription?.count == 0 { print("nil returnUniSecurityDescription for \(mySymbol)") }
                // print("DESCRIPTIONS COUNTER = \(counter)")
                counter -= 1
                var myDescription = UNISecurityDescription()
                if returnUNISecurityDescription != nil, returnUNISecurityDescription?.count != 0 { myDescription = returnUNISecurityDescription![0]  }
                if myDescription.name == nil || myDescription.name == "" { print("Error: No Name for \(String(describing: mySymbol))") }
                let myContainersIndices = self.myUNIList.singleContainer.indices.filter({ self.myUNIList.singleContainer[$0].ticker?.symbol == mySymbol })
                var myPathArray = [IndexPath]()
                for index in 0..<myContainersIndices.count {
                    self.myUNIList.singleContainer[myContainersIndices[index]].name = myDescription.name
                    self.myUNIList.singleContainer[myContainersIndices[index]].currencySymbol = myDescription.currencySymbol
                    self.myUNIList.singleContainer[myContainersIndices[index]].fillFundamentals() // --> Fills the outputs for sortdata
                    myPathArray.append(IndexPath(row: myContainersIndices[index], section: 0))
                }
                DispatchQueue.main.async {
                    self.filteredData = self.myUNIList.singleContainer
                    self.myCollection?.reloadItems(at: myPathArray)
                }
                if counter == 0     {   // THIS IS TRUE MORE THAN ONCE WHILE IT SHOULD NOT BE TRU MORE THAN ONCE
                    if doubleCount > 0 {    print("WHY!!!!")  }
                    doubleCount += 1
                    print("DESCRIPTIONS counter = \(counter) -> \(self.myUNIList.listName) - symbols: \(String(describing: mySymbols?.count)) \n==================================================\n")
                    DispatchQueue.main.async {   self.sortNormalTap("Load")  { _ in     self.displayAfterLoading()  } }
                    completion(true)
                    return
                }
            }
        }
    }

要满足的条件是计数器== 0。一旦满足了这一点,函数就会完成并退出DispatchGroup。问题是计数器== 0多次为真(在退出DispatchGroup时明显崩溃)。我真的不明白为什么这个条件会不止一次得到满足。代码是非常线性的,我看不出是什么导致了这种情况。任何帮助都是非常感谢的。这快把我逼疯了。

EN

回答 2

Stack Overflow用户

发布于 2020-11-11 22:05:54

你的代码不是线程安全的,特别是计数器。我用你同样的逻辑写了一个例子来说明这一点。如果你运行几次,你最终会遇到和你的问题相同的情况。

代码语言:javascript
代码运行次数:0
复制
override func viewDidLoad() {
    super.viewDidLoad()

    let mySymbols: [Int] = Array(0...100)

    for _ in 0..<100 {
        xxxfastLoadLSecurityDescriptions(session: URLSession.shared, mySymbols: mySymbols) { (success, counter, doubleCount) in
            print("Completed: \(success), Counter: \(counter), Double Count: \(doubleCount)")
        }
    }
}

private func xxxfastLoadLSecurityDescriptions(session: URLSession, mySymbols: [Int]?, completion: @escaping(Bool, Int, Int) ->())    {

    var counter = mySymbols?.count ?? 0

    if counter == 0 {
        return completion(false, -1, -1)
    }
    var doubleCount = 0

    for symbolIndex in 0..<(mySymbols?.count ?? 0) {
        guard let _ = mySymbols?[symbolIndex] else {
            print("Error")
            continue
        }

        DispatchQueue.global().asyncAfter(deadline: .now() + .milliseconds(Int.random(in: 50..<900))) {

            counter -= 1

            DispatchQueue.main.async {
                self.view.layoutIfNeeded()
            }

            if counter == 0 {
                if doubleCount > 0 {
                    // This will eventually print even though logically it shouldn't
                    print("*****Counter: \(counter), Double Count: \(doubleCount), Symbol Index: \(symbolIndex)")
                }
                doubleCount += 1
                completion(true, counter, doubleCount)
                return
            }
        }
    }
}

输出:

代码语言:javascript
代码运行次数:0
复制
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
*******************************************************************
*****   Counter: 0, Double Count: 1, Symbol Index: 15   
*******************************************************************
Completed: true, Counter: 0, Double Count: 2
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
*******************************************************************
*****   Counter: 0, Double Count: 1, Symbol Index: 26   
*******************************************************************
Completed: true, Counter: 0, Double Count: 2
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
Completed: true, Counter: 0, Double Count: 1
*******************************************************************
*****   Counter: 0, Double Count: 1, Symbol Index: 57   
*******************************************************************
Completed: true, Counter: 0, Double Count: 2
*******************************************************************
*****   Counter: 0, Double Count: 1, Symbol Index: 3    
*******************************************************************
Completed: true, Counter: 0, Double Count: 2
票数 1
EN

Stack Overflow用户

发布于 2020-11-12 08:57:43

最后,我使用DispatchGroup解决了这个问题(简化代码):

代码语言:javascript
代码运行次数:0
复制
private func xxxFastLoadLSecurityDescriptions(session: URLSession, mySymbols: [String]?, completion: @escaping(Bool) ->())    {
    
    let myGroup = DispatchGroup()
    
    for symbolIndex in 0..<(mySymbols?.count ?? 0) {
        
        myGroup.enter()
    
        mySessionSendMGBGenericRequest(...) { [weak self] returnValue in
            
            guard let self = self else { myGroup.leave() ; return }
         // do some stuff with returnValue
            
            myGroup.leave()
        }
    }
    
    myGroup.notify(queue: .main, execute: {
        
        completion(true)
    })
}

我的问题是:我有没有可能遇到和以前一样的问题?例如,假设我有一个针对2个项目的循环。第一个项目进入组,并在第二个项目进入循环之前,异步调用返回一个值,第一个项目退出组。此时,在第二个项目进入组之前,应触发.notify,并在处理第二个项目之前完成(True)函数。这个是可能的吗?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64791778

复制
相关文章
kubesphere无法更新项目
        kubesphere集群部署了一段时间了,今天需要更新镜像版本,然而在kubesphere页面点击”重新部署“按钮,虽然页面提示”部署成功“,但实际上没一点反应,kubephere关于这个问题可以优化下,如下图所示。
johnhuster的分享
2022/11/07
1.5K0
kubesphere无法更新项目
pycharm 如何更新本地项目文件[通俗易懂]
本地更新项目文件后,pycharm不会自动更新导航栏的文件目录,运行程序时报错,找不到文件:
全栈程序员站长
2022/09/25
1.1K0
pycharm 如何更新本地项目文件[通俗易懂]
EasyCVR更新版本后无法清除数据库已删除文件,该如何解决?
EasyCVR视频融合云服务基于云边端一体化架构,具有强大的数据接入、处理及分发能力,平台支持海量视频汇聚管理,可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、语音对讲、智能分析等视频能力。
TSINGSEE青犀视频
2023/02/07
8300
项目打包成 jar 后包无法读取src/main/resources下文件
该代码功能是利用 common.io 包下的FileUtils来读取文件, 放到一个字符串中
时间静止不是简史
2022/05/06
13.4K0
项目打包成 jar 后包无法读取src/main/resources下文件
Pages 无法使用此AppleID更新
无法更新是因为这个应用并没有绑定到已经登录的AppleID中,点击已购,会提示有应用需要接受,点击全部接受。输入几次密码之后再次更新就ok了、
obaby
2023/02/23
9920
Debian 无法更新和镜像源
位于一台德国的vps, 用的 Debian, 这个逼最近, 突然apt-get 不好使了. 各种error .
chuchur
2023/09/13
9430
vue项目中swiper动态更新后无法轮播问题 附带案例代码
swiper是很常用的一个组件,我项目中用到的版本是4.1.6。刚开始,我就按照官网的案例写了个demo,当然图片都是静态写死的,确实可以轮播了,但是我项目的需求是要动态修改轮播图的内容。然后我就改成vue的方式了,js和css是通过cdn引入的。下面是swiper的全部代码: 有问题请加群交流java群:200909980,vue群:128806068 ,或者在下边评论 vue template 代码 轮播内容是通过循环数组自动生成的 <div class="swiper-container" v-
码农笔录
2018/06/29
2.2K0
matlab中importdata无法打开文件_importdata无法打开文件
最近使用importdata函数不能读取全部数据,数据集315行,但是读取了197行,那就是197-198之间有问题,百度之后有了思路。由于没有找到具体的证据,所以这里说一下解决思路。
全栈程序员站长
2022/11/16
6.2K0
matlab中importdata无法打开文件_importdata无法打开文件
安防视频监控平台EasyCVR数据库字段无法更新,如何优化?
关于EasyCVR数据库相关的技术文章,我们在前期也分享了很多,包括功能优化及疑难问题解决等,感兴趣的用户可以翻阅我们往期的文章进行了解。近期我们对EasyCVR数据库的字段进行了优化,今天来和大家分享一下。
TSINGSEE青犀视频
2022/07/20
6250
jar命令更新SpringBoot项目jar包里的补丁文件
最近在因为项目依赖了太多微服务的包,所以项目经常报错,又因为在联调接口,需要经常打包,所以想直接在springboot项目的一个jar包直接加上自己的补丁,然后重新部署就行,提高效率
SmileNicky
2022/09/21
2.4K0
GitHub 更新:更新 timeline & 相似项目推荐
一大早在微信群里,听说 GitHub 更新了,打开电脑一看果然是更新了。首页的动态发生了一些变化: 这一下子,能看到的东西比以前更少了。每天要涨那么多 star 的我,有点纠结。 与此同时,开始为您推
Phodal
2018/01/29
1.5K0
案例详解:Linux文件系统异常导致数据库文件无法访问
墨墨导读:某客户单位数据库出现异常,大致现象是:数据库状态是open的,但是其中一个数据文件无法访问,本文分享排查原因与解决问题的整个过程。
数据和云
2020/06/01
1.7K0
beegfs 7.3.2更新后服务无法启动
beegfs 7.3.2版本默认强制身份验证身份。所以在安装或升级后,没有配置authfile会导致服务无法启动。
姚华
2023/02/22
2K0
IMP-00002: 无法打开 F:\Work\项目\数据库文件\gi_data.dmp; 进行读取
IMP-00002: 无法打开 F:\Work\项目\新疆\数据库文件\gi_data.dmp; 进行读取 导入文件: EXPDAT.DMP>
西门呀在吹雪
2020/11/09
2.7K0
IMP-00002: 无法打开 F:\Work\项目\数据库文件\gi_data.dmp; 进行读取
kali修改更新源(无法安全的用该源更新)
因为kali是国外的,所以一些软件你要下载的话得从国外的网站下载,就会很慢,国内一些公司或者学校提供了国内的下载地址,所以我们需要更换更新源
全栈程序员站长
2022/07/25
1.8K0
解决 WordPress 无法自动检查更新
自 wordpress 3.7开始,自动更新已经默认开启。小版本更新将全自动运行,无需人工干预。但在 reizhi 的博客却遇到了一些问题,wordpress 不但无法自动更新,在更新界面也看不到最新的版本信息。如下图所示,下载后本应显示服务器端最新版本号,但在此只显示了一个横线。起初以为是版本号丢失,但查看 wordpress 后台底部却能够正确显示当前版本。重装过数次虽然能短暂解决,过一段时间之后又再次出现。 
reizhi
2022/09/26
1.4K0
解决 WordPress 无法自动检查更新
ActionScript项目无法调试[通俗易懂]
C:\WINDOWS\system32\Macromed\Flash\Flash10b.ocx
全栈程序员站长
2022/11/04
4900
Qt项目网络聊天室设计
3. 服务器接收到某个客户端的请求以及发送信息,经服务器发给其它客户端 最终实现一个共享聊天内容的聊天室!
DeROy
2020/08/19
2.4K0
Qt项目网络聊天室设计
GitHub文件下载慢?无法克隆项目?多种方法提升项目下载与克隆体验
GitHub,或许是全球最大的代码托管与开源社区了。虽然现在代码托管,可以使用Coding,并且可以和腾讯云服务器很好的有机结合(比如:Coding作为仓库,腾讯云轻量应用服务器作为K8s发布平台,实现自动化部署),但是如果是需要代码开源和社区反馈,往往还是选择GitHub。
Mintimate
2022/05/26
3K0
GitHub文件下载慢?无法克隆项目?多种方法提升项目下载与克隆体验
tomcat项目无法启动
1.打开未加载成功的项目属性,即Properties 2.点开Depolyment Assembly,查看web.xml目录是否有添加在其中,即红框,未添加则添加,即可解决tomcat启动没有加载项目,因为找不到web.xml 3.webapp这个路径是因为该项目为maven项目,所以必须配置这个路径,否则会启动失败,找不到相关的jar包
Java架构师必看
2021/05/19
2K0

相似问题

将html按钮单击与objective c绑定

10

通过objective-c触发HTML按钮单击?

21

在C++代码中处理HTML按钮单击事件

11

批注中的objective c mapkit单击按钮

11

在objective c中单击按钮时的容器视图

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文