草庐IT

swift - 在 Swift 中调度两个独立的异步线程

coder 2023-09-11 原文

我正在尝试加载一组按钮,这些按钮将在加载菜单时一个接一个地滑入。所以我这样做了:

    buttonTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(MainMenu.enterButtons), userInfo: nil, repeats: true)
    buttonTimer.fire()

这将运行 enterButtons() 方法,该方法将运行按钮的移动 Action 。这个计时器是在这个菜单的初始化过程中创建的,因为我希望按钮在初始化时加载。然而,在我的初始化过程中,我还初始化了一个性能很重的类,因为它包含我所有的级别:

    DispatchQueue.main.asyncAfter(deadline: .now()) {
        self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))
    }

所以我以异步方式执行此操作,因为如果我不这样做,它将阻止初始化程序的所有其他功能。但是,我认为这两个线程实际上只是一个线程。异步任务的顺序是:

  1. 初始化级别持有者
  2. 加载按钮

我希望这两个任务能同时运行。然而,似乎我希望的不是三个线程(主线程,一个用于关卡持有者,一个用于加载按钮)我相信只有两个:主线程和一个用于我创建的两个异步任务.在我的调试 session 期间,我注意到加载按钮任务等待级别持有者被初始化。但是,我想创建三个独立的异步线程。我该怎么做?

编辑

我尝试为关卡持有者实现并发我试过这个,@UpholderOfTruth 建议:

    DispatchQueue.global(qos: .background) {
        self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))
    }

但我收到一条错误消息:

LevelHolder is not convertible to 'LevelHolder!'

因为 self.initialLevel.levelHolder 是 LevelHolder 类型!但我将其设置为等于 LevelHolder。

我怎样才能避免这个错误?我试过这样做:

self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))!

但是 Xcode 会提示警告我

cannot force unwrap to a non-optional type 'LevelHolder'

initialLevel 在初始化关卡持有者的方法中被初始化:

func initializeLevelHolder() {
    initialLevel = InitialLevel()
    initialLevel.size = self.size
    DispatchQueue.main.asyncAfter(deadline: .now()) {
        self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))
    }
}

它是这个菜单的一个实例变量,定义为

var initialLevel : InitialLevel!

最佳答案

您立即将 levelHolder 代码推回主线程,并将按钮时间设置为在 0.1 秒后触发,然后在方法完成后手动触发它。所以一切都在主线程上发生,你的 levelHolder 处理阻止了按钮处理。

您可以像这样将 levelHolder 处理放到后台线程上:

DispatchQueue.global(qos: .background).async {
    self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))
}

但是不要忘记对 UI 的任何更新仍然需要像这样返回主线程:

DispatchQueue.main.async {
    // Update the UI
}

不幸的是,对此我们无能为力,因为所有 UI 更新都必须在主线程上进行,因此会在一定程度上相互阻塞。

关于swift - 在 Swift 中调度两个独立的异步线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44468706/

有关swift - 在 Swift 中调度两个独立的异步线程的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  4. ruby - 这两个 Ruby 类初始化定义有什么区别? - 2

    我正在阅读一本关于Ruby的书,作者在编写类初始化定义时使用的形式与他在本书前几节中使用的形式略有不同。它看起来像这样:classTicketattr_accessor:venue,:datedefinitialize(venue,date)self.venue=venueself.date=dateendend在本书的前几节中,它的定义如下:classTicketattr_accessor:venue,:datedefinitialize(venue,date)@venue=venue@date=dateendend在第一个示例中使用setter方法与在第二个示例中使用实例变量之间是

  5. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  6. ruby - 如何让Ruby捕获线程中的语法错误 - 2

    我正在尝试使用ruby​​编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?

  7. ruby - 如何在 ruby​​ 中运行后台线程? - 2

    我是ruby​​的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp

  8. ruby - 具有两个参数的 block - 2

    我从用户Hirolau那里找到了这段代码:defsum_to_n?(a,n)a.combination(2).find{|x,y|x+y==n}enda=[1,2,3,4,5]sum_to_n?(a,9)#=>[4,5]sum_to_n?(a,11)#=>nil我如何知道何时可以将两个参数发送到预定义方法(如find)?我不清楚,因为有时它不起作用。这是重新定义的东西吗? 最佳答案 如果您查看Enumerable#find的文档,您会发现它只接受一个block参数。您可以将它发送两次的原因是因为Ruby可以方便地让您根据它的“并行赋

  9. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  10. ruby - Rails 开发服务器、PDFKit 和多线程 - 2

    我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它:

随机推荐