天道酬勤,学无止境

如何以及何时在Julia中使用@async和@sync(How and When to Use @async and @sync in Julia)

问题

我已经阅读了@async@sync宏的文档,但仍然无法弄清楚如何以及何时使用它们,也无法在Internet上的其他地方找到许多关于它们的资源或示例。

我的近期目标是找到一种方法来设置多个工作人员并行执行工作,然后等到他们全部完成我的代码后再进行工作。 这篇文章:等待在Julia中的远程处理器上完成任务包含一种成功的方法。 我曾经以为可以使用@async@sync宏,但是我最初的失败是想知道我是否正确理解了如何以及何时使用这些宏。

回答1

根据?@async下的文档,“ @async将表达式包装在Task中。” 这意味着,对于处于其范围内的任何内容,Julia都会开始运行此任务,然后继续执行脚本中的下一个内容,而无需等待任务完成。 因此,例如,没有宏,您将得到:

julia> @time sleep(2)
  2.005766 seconds (13 allocations: 624 bytes)

但是使用宏,您将获得:

julia> @time @async sleep(2)
  0.000021 seconds (7 allocations: 657 bytes)
Task (waiting) @0x0000000112a65ba0

julia> 

因此,Julia允许脚本继续执行(并使@time宏完全执行),而无需等待任务(在本例中为休眠状态,等待两秒钟)完成。

相比之下, @sync宏将“等待,直到@async@spawn@spawnat@parallel所有动态封闭使用都完成@parallel 。” (根据?@sync下的文档)。 因此,我们看到:

julia> @time @sync @async sleep(2)
  2.002899 seconds (47 allocations: 2.986 KB)
Task (done) @0x0000000112bd2e00

那么,在这个简单的示例中,没有必要将@async@sync的单个实例包括在一起。 但是, @sync很有用的地方是您将@async应用于了多个操作,希望这些操作一次全部开始而无需等待每个操作完成。

例如,假设我们有多个工作人员,并且我们想开始让他们每个人同时处理一个任务,然后从这些任务中获取结果。 最初(但不正确)的尝试可能是:

using Distributed
cell(N) = Vector{Any}(undef, N)

addprocs(2)
@time begin
    a = cell(nworkers())
    for (idx, pid) in enumerate(workers())
        a[idx] = remotecall_fetch(sleep, pid, 2)
    end
end
## 4.011576 seconds (177 allocations: 9.734 KB)

这里的问题是循环在继续下一个remotecall_fetch()操作之前,等待每个remotecall_fetch()操作完成,即等待每个进程完成其工作(在本例中为2秒)。 在实际情况中,由于我们的流程无法同时完成其工作(即睡眠),因此我们在这里没有获得并行性的好处。

但是,我们可以结合使用@async@sync宏来更正此问题:

@time begin
    a = cell(nworkers())
    @sync for (idx, pid) in enumerate(workers())
        @async a[idx] = remotecall_fetch(sleep, pid, 2)
    end
end
## 2.009416 seconds (274 allocations: 25.592 KB)

现在,如果将循环的每个步骤都算作一个单独的操作,我们会看到在@async宏之前有两个单独的操作。 宏允许它们中的每一个启动,并且代码在每个完成之前继续(在这种情况下,进入循环的下一步)。 但是,使用@sync宏(其范围涵盖整个循环)意味着我们不允许脚本执行该循环,直到@async之前的所有操作都已完成。

通过进一步调整上面的示例以查看在某些修改下它是如何变化的,可以对这些宏的操作有一个更加清晰的了解。 例如,假设我们只有@async而没有@sync

@time begin
    a = cell(nworkers())
    for (idx, pid) in enumerate(workers())
        println("sending work to $pid")
        @async a[idx] = remotecall_fetch(sleep, pid, 2)
    end
end
## 0.001429 seconds (27 allocations: 2.234 KB)

在这里, @async宏允许我们在每个remotecall_fetch()操作完成执行之前继续循环。 但是, @sync好坏,我们没有@sync宏来阻止代码继续通过此循环,直到所有remotecall_fetch()操作完成为止。

但是,即使我们继续进行操作,每个remotecall_fetch()操作仍在并行运行。 我们可以看到,因为如果我们等待两秒钟,那么包含结果的数组a将包含:

sleep(2)
julia> a
2-element Array{Any,1}:
 nothing
 nothing

(“ nothing”元素是成功获取sleep函数的结果的结果,该函数不返回任何值)

我们还可以看到,这两个remotecall_fetch()操作基本上是同时启动的,因为它们前面的打印命令也会快速连续执行(这些命令的输出未在此处显示)。 与下面的示例相反,在下一个示例中,打印命令彼此之间的延迟为2秒:

如果我们将@async宏放在整个循环中(而不只是它的内部步骤),那么我们的脚本将再次立即继续运行,而无需等待remotecall_fetch()操作完成。 但是,现在,我们只允许脚本从整个循环继续进行。 我们不允许循环的每个步骤在上一个步骤结束之前开始。 因此,与上面的示例不同,脚本在循环后继续执行两秒钟后,结果数组仍具有一个元素,如#undef,表明第二个remotecall_fetch()操作仍未完成。

@time begin
    a = cell(nworkers())
    @async for (idx, pid) in enumerate(workers())
        println("sending work to $pid")
        a[idx] = remotecall_fetch(sleep, pid, 2)
    end
end
# 0.001279 seconds (328 allocations: 21.354 KB)
# Task (waiting) @0x0000000115ec9120
## This also allows us to continue to

sleep(2)

a
2-element Array{Any,1}:
    nothing
 #undef    

而且,毫不奇怪,如果我们将@sync@async紧挨着,我们将获得每个remotecall_fetch()顺序运行(而不是同时运行)的信息,但是直到它们完成后我们才继续执行代码。 换句话说,我认为这基本上等同于如果我们都没有宏,就像sleep(2)行为与@sync @async sleep(2)行为基本相同

@time begin
    a = cell(nworkers())
    @sync @async for (idx, pid) in enumerate(workers())
        a[idx] = remotecall_fetch(sleep, pid, 2)
    end
end
# 4.019500 seconds (4.20 k allocations: 216.964 KB)
# Task (done) @0x0000000115e52a10

还要注意,在@async宏的范围内可能有更复杂的操作。 该文档提供了一个示例,其中包含@async范围内的整个循环。

更新:回想一下同步宏的帮助,它会“等待,直到@async@spawn@spawnat@parallel所有动态封闭使用都完成@parallel ”。 对于什么@sync是“完成”而言,如何在@sync@async宏范围内定义任务很重要。 考虑下面的示例,它与上面给出的示例之一略有不同:

@time begin
    a = cell(nworkers())
    @sync for (idx, pid) in enumerate(workers())
        @async a[idx] = remotecall(sleep, pid, 2)
    end
end
## 0.172479 seconds (93.42 k allocations: 3.900 MB)

julia> a
2-element Array{Any,1}:
 RemoteRef{Channel{Any}}(2,1,3)
 RemoteRef{Channel{Any}}(3,1,4)

前面的示例执行大约需要2秒钟的时间,这表明两个任务是并行运行的,并且脚本在继续执行之前等待每个任务完成其功能。 但是,此示例的评估时间要短得多。 原因是出于@sync的目的, @sync remotecall()操作向工作人员发送了要执行的工作,它就“完成”了。 (请注意,结果数组a在这里仅包含RemoteRef对象类型,这仅表示特定进程正在发生某些事情,理论上可以在将来的某个时间获取)。 相比之下,当remotecall_fetch()操作从工作人员获得消息说其任务已完成时,它仅“完成”。

因此,如果您正在寻找方法来确保对工作人员的某些操作在脚本中继续进行之前已经完成(例如,如本文章中所讨论的:等待在Julia中的远程处理器上完成任务),则有必要仔细考虑什么才算是“完整”,以及如何在脚本中对其进行衡量和实施。

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • How and When to Use @async and @sync in Julia
    I have read the documentation for the @async and @sync macros but still cannot figure out how and when to use them, nor can I find many resources or examples for them elsewhere on the internet. My immediate goal is to find a way to set several workers to do work in parallel and then wait until they have all finished to proceed in my code. This post: Waiting for a task to be completed on remote processor in Julia contains one successful way to accomplish this. I had thought it should be possible using the @async and @sync macros, but my initial failures to accomplish this made me wonder if I am
  • DispatchQueue.main.async和DispatchQueue.main.sync之间的区别(Difference between DispatchQueue.main.async and DispatchQueue.main.sync)
    问题 我已经使用DispatchQueue.main.async很长时间了,以执行与UI相关的操作。 Swift提供了DispatchQueue.main.async和DispatchQueue.main.sync ,并且两者都在主队列上执行。 谁能告诉我他们之间的区别? 我什么时候应该使用每个? DispatchQueue.main.async { self.imageView.image = imageView self.lbltitle.text = "" } DispatchQueue.main.sync { self.imageView.image = imageView self.lbltitle.text = "" } 回答1 使用async它可以使调用队列继续前进,而不必等到调度的块执行完毕。 相反, sync将使调用队列停止并等待,直到您在块中分派的工作完成为止。 因此, sync会导致死锁。 尝试从主队列中运行DispatchQueue.main.sync ,该应用程序将冻结,因为调用队列将等待直到分派的块结束,但它甚至无法启动(因为队列已停止并正在等待) 何时使用sync ? 当您需要等待在不同队列上完成的事情然后才继续在当前队列上工作时 使用同步的示例: 在串行队列上,您可以将sync用作互斥体,以确保只有一个线程能够同时执行受保护的代码段。 回答2
  • 何时在jquery的ajax函数中使用async false和async true(When to use async false and async true in ajax function in jquery)
    问题 何时使用ajax调用中使用async false或async true。 就性能而言,有什么不同吗? 例子 : $.ajax({ url : endpoint, type : "post", async : false, success : function(data) { if (i==1){ getMetricData(data)} else if (i==2) { capture = data; } } }); 回答1 这与性能无关... 当需要在浏览器传递给其他代码之前完成该ajax请求时,请将async设置为false: <script> // ... $.ajax(... async: false ...); // Hey browser! first complete this request, // then go for other codes $.ajax(...); // Executed after the completion of the previous async:false request. </script> 回答2 当异步设置设置为false时,将进行同步调用而不是异步调用。 将jQuery AJAX函数的异步设置设置为true时,将进行jQuery异步调用。 AJAX本身意味着异步JavaScript和XML,因此
  • 调度队列:如何判断它们是否正在运行以及如何停止它们(Dispatch queues: How to tell if they're running and how to stop them)
    问题 我只是在玩GCD,我已经编写了一个玩具CoinFlipper应用程序。 这是掷硬币的方法: - (void)flipCoins:(NSUInteger)nFlips{ // Create the queues for work dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL); // Split the number of flips into whole chunks of kChunkSize and the remainder. NSUInteger numberOfWholeChunks = nFlips / kChunkSize; NSUInteger numberOfRemainingFlips = nFlips - numberOfWholeChunks * kChunkSize; if (numberOfWholeChunks > 0) { for (NSUInteger index = 0; index < numberOfWholeChunks; index++) { dispatch_async(queue, ^{
  • 在Swift 3,Swift 4及更高版本中,我该如何使用dispatch_sync,dispatch_async,dispatch_after等?(How do I dispatch_sync, dispatch_async, dispatch_after, etc in Swift 3, Swift 4, and beyond?)
    问题 我在Swift 2.x(甚至1.x)项目中有很多代码,如下所示: // Move to a background thread to do some long running work dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { let image = self.loadOrGenerateAnImage() // Bounce back to the main thread to update the UI dispatch_async(dispatch_get_main_queue()) { self.imageView.image = image } } 或类似这样的东西来延迟执行: dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { print("test") } 或Grand Central Dispatch API的所有其他各种用途... 既然我已经在Swift 3的Xcode 8(测试版)中打开了我的项目,就会遇到各种各样的错误。 其中一些提供了修复我的代码的功能
  • 何时正确使用Task.Run以及何时仅异步等待(When correctly use Task.Run and when just async-await)
    问题 我想问您关于何时使用Task.Run的正确体系结构的Task.Run 。 我在WPF .NET 4.5应用程序(使用Caliburn Micro框架)中遇到了滞后的UI。 基本上我在做(非常简化的代码片段): public class PageViewModel : IHandle<SomeMessage> { ... public async void Handle(SomeMessage message) { ShowLoadingAnimation(); // Makes UI very laggy, but still not dead await this.contentLoader.LoadContentAsync(); HideLoadingAnimation(); } } public class ContentLoader { public async Task LoadContentAsync() { await DoCpuBoundWorkAsync(); await DoIoBoundWorkAsync(); await DoCpuBoundWorkAsync(); // I am not really sure what all I can consider as CPU bound as slowing down the UI await
  • 朱莉娅:如何将数据复制到朱莉娅中的另一个处理器(Julia: How to copy data to another processor in Julia)
    问题 如何在Julia中将数据从一个处理器移动到另一个处理器? 说我有一个数组 a = [1:10] 或其他一些数据结构。 将其放在所有其他可用处理器上的正确方法是什么,以使其以相同的变量名在这些处理器上可用? 回答1 一开始我不知道该怎么做,所以我花了一些时间弄清楚它。 这是我为传递对象而编写的一些函数: sendto 将任意数量的变量发送到指定的进程。 在指定过程的主模块中创建新变量。 名称将是关键字参数的键,而值将是关联的值。 function sendto(p::Int; args...) for (nm, val) in args @spawnat(p, eval(Main, Expr(:(=), nm, val))) end end function sendto(ps::Vector{Int}; args...) for p in ps sendto(p; args...) end end 例子 # creates an integer x and Matrix y on processes 1 and 2 sendto([1, 2], x=100, y=rand(2, 3)) # create a variable here, then send it everywhere else z = randn(10, 10); sendto(workers(), z=z)
  • 如何从WPF gui运行异步任务并与之交互(How to run and interact with an async Task from a WPF gui)
    问题 我有一个WPF GUI,在这里我想按一个按钮来启动一个长任务,而不会在任务期间冻结窗口。 在任务运行时,我想获取进度报告,并且希望合并另一个按钮,该按钮将在我选择的任何时间停止任务。 我无法弄清楚使用异步/等待/任务的正确方法。 我无法提供我尝试过的所有内容,但这就是我目前所拥有的。 WPF窗口类: public partial class MainWindow : Window { readonly otherClass _burnBabyBurn = new OtherClass(); internal bool StopWorking = false; //A button method to start the long running method private async void Button_Click_3(object sender, RoutedEventArgs e) { Task slowBurn = _burnBabyBurn.ExecuteLongProcedureAsync(this, intParam1, intParam2, intParam3); await slowBurn; } //A button Method to interrupt and stop the long running method private void
  • 脚本标签-异步和延迟(Script Tag - async & defer)
    问题 我对<script>标记的属性async & defer有几个问题,据我了解,这些属性仅在HTML5浏览器中有效。 我的一个网站有两个外部JavaScript文件,这些文件当前位于</body>标记上方; 第一个是来自Google的jquery,第二个是本地外部脚本。 关于站点加载速度 将async添加到页面底部的两个脚本中是否有任何优势? 将async选项添加到两个脚本并将它们放在<head>页面的顶部是否有任何优势? 这是否意味着它们会在页面加载时下载? 我认为这会导致HTML4浏览器的延迟,但是会加快HTML5浏览器的页面加载速度吗? 使用<script defer src=... 将加载内部的两个脚本<head>与属性defer如前所述具有脚本相同影响</body> 我再次假设这会减慢HTML4浏览器的速度。 使用<script async src=... 如果我有两个启用了async脚本 他们会同时下载吗? 还是一次与其余页面一起? 脚本的顺序是否会成为问题? 例如,一个脚本依赖于另一个脚本,因此,如果一个脚本下载速度更快,则第二个脚本可能无法正确执行等。 最后,在HTML5更广泛使用之前,我最好还是保持现状吗? 回答1 将脚本保持在</body>之前。 在某些情况下,异步可以与位于此处的脚本一起使用(请参见下面的讨论)。 Defer不会对位于此处的脚本产生太大影响
  • console.log()异步还是同步?(console.log() async or sync?)
    问题 我目前正在阅读Trevor Burnham撰写的Async Javascript。 到目前为止,这是一本很棒的书。 他谈到了这个片段和console.log在Safari和Chrome控制台中是“异步”的。 不幸的是,我无法复制这一点。 这是代码: var obj = {}; console.log(obj); obj.foo = 'bar'; // my outcome: Object{}; 'bar'; // The book outcome: {foo:bar}; 如果这是异步的,我希望结果就是书籍的结果。 将console.log()放到事件队列中,直到执行完所有代码为止,然后将其运行并具有bar属性。 尽管它正在同步运行,但它似乎出现了。 我运行此代码是否错误? console.log实际上是异步的吗? 回答1 console.log不是标准化的,因此行为是相当不确定的,并且可以在开发人员工具的发行之间轻松地进行更改。 您的书很可能已经过时,很快我的回答也可能会过时。 对于我们的代码, console.log是否异步没有什么区别,它不提供任何回调方法。 并且您传递的值始终在调用函数时进行引用和计算。 我们真的不知道接下来会发生什么(好的,我们可以,因为Firebug,Chrome Devtools和Opera Dragonfly都是开源的)。
  • 如何在.NET中产生并等待实现控制流?(How do yield and await implement flow of control in .NET?)
    问题 据我了解yield关键字,如果从迭代器块内部使用它,它将控制流返回到调用代码,并且当再次调用迭代器时,它将从中断的地方开始。 同样, await不仅等待被调用方,而且将控制权返回给调用方,仅在调用方awaits该方法时才从中断处接管。 换句话说,没有线程,异步和等待的“并发性”是由聪明的控制流引起的错觉,其细节被语法隐藏了。 现在,我是一名前汇编程序员,并且对指令指针,堆栈等非常熟悉,并且了解了正常的控制流程(子例程,递归,循环,分支)的工作方式。 但是这些新结构-我不明白。 当到达await状态时,运行时如何知道下一步应该执行什么代码? 它如何知道何时可以从上次中断的地方恢复,以及如何记住在哪里? 当前调用堆栈发生了什么,是否以某种方式保存了该堆栈? 如果调用方法在await之前进行其他方法调用怎么办-为什么堆栈不被覆盖? 在异常和堆栈展开的情况下,运行时如何在所有这些方面进行工作? 当达到yield时,运行时如何跟踪应该拾取的点? 迭代器状态如何保存? 回答1 我将在下面回答您的特定问题,但是您可能会很容易阅读我有关如何设计产量和等待时间的大量文章。 https://blogs.msdn.microsoft.com/ericlippert/tag/continuation-passing-style/ https://blogs.msdn.microsoft.com
  • When to use Task.Delay, when to use Thread.Sleep?(When to use Task.Delay, when to use Thread.Sleep?)
    问题 是否有使用何时使用Task.Delay和Thread.Sleep的良好规则? 具体来说,是否存在一个最小值才能使一个相对于另一个有效/高效? 最后,由于Task.Delay导致在异步/等待状态机上进行上下文切换,因此使用它会产生开销吗? 回答1 要阻止当前线程时,请使用Thread.Sleep。 如果需要逻辑延迟而不阻塞当前线程,请使用Task.Delay。 效率不应该是这些方法的头等大事。 它们在现实世界中的主要用途是作为I / O操作的重试计时器,其数量级为秒而不是毫秒。 回答2 Task.Delay和Thread.Sleep之间的最大区别是Task.Delay旨在异步运行。 在同步代码中使用Task.Delay没有意义。 在异步代码中使用Thread.Sleep是一个非常糟糕的主意。 通常,您将使用await关键字调用Task.Delay() : await Task.Delay(5000); 或者,如果您想在延迟之前运行一些代码: var sw = new Stopwatch(); sw.Start(); Task delay = Task.Delay(5000); Console.WriteLine("async: Running for {0} seconds", sw.Elapsed.TotalSeconds); await delay; 猜猜这将打印什么?
  • 何时使用Spring @Async与Callable控制器(异步控制器,Servlet 3)(When to use Spring @Async vs Callable controller (async controller, servlet 3))
    问题 我想知道在Spring中使用Callable使用@Async和Servlet 3异步请求实现的一般用例。 据我了解,@ Async用于使任何方法(特别是任何服务方法)异步执行。 @Async void doSomething(String s) { // this will be executed asynchronously } 以及任何返回Callable的控制器 @RequestMapping("/view") public Callable<String> callableWithView(final Model model) { return new Callable<String>() { @Override public String call() throws Exception { Thread.sleep(2000); model.addAttribute("foo", "bar"); model.addAttribute("fruit", "apple"); return "views/html"; } }; } 我对何时使用什么感到困惑。 将异步servlet /控制器与spring @Async一起使用会产生什么效果? 回答1 这篇文章解释了您要寻找的东西 摘抄: 在某些情况下,您可以在后台作业完成处理后立即返回客户端。 例如发送电子邮件
  • GCD中的并发与串行队列(Concurrent vs serial queues in GCD)
    问题 我正在努力完全理解GCD中的并发和串行队列。 我遇到了一些问题,希望有人能及时明确地回答我。 我正在阅读串行队列的创建和使用,以便一个接一个地执行任务。 但是,如果发生以下情况,会发生什么情况: 我创建一个串行队列我使用dispatch_async (在刚创建的串行队列上)三次来调度三个块A,B,C 将执行以下三个块: 顺序为A,B,C,因为队列是串行的或者同时(在并行线程上),因为我使用了ASYNC调度我读到我可以在并发队列上使用dispatch_sync ,以便一个接一个地执行块。 在那种情况下,为什么甚至不存在串行队列,因为我总是可以使用并发队列,在该队列中我可以根据需要同步分发尽可能多的块? 感谢您的任何很好的解释! 回答1 一个简单的例子:您有一个需要一分钟执行的块。 您将其从主线程添加到队列中。 让我们看一下这四种情况。 异步-并发:代码在后台线程上运行。 控件立即返回主线程(和UI)。 该块不能假定它是在该队列上运行的唯一块异步-串行:代码在后台线程上运行。 控制权立即返回主线程。 该块可以假定它是在该队列上运行的唯一块 sync-并发:代码在后台线程上运行,但主线程等待其完成,从而阻止对UI的任何更新。 该块不能假定它是在该队列上运行的唯一块(我本可以在几秒钟前使用异步添加另一个块) sync-串行:代码在后台线程上运行,但是主线程等待它完成
  • 何时或是否在调用ReadAsStreamAsync时处置HttpResponseMessage?(When or if to Dispose HttpResponseMessage when calling ReadAsStreamAsync?)
    问题 我正在使用System.Net.Http.HttpClient进行一些客户端HTTP通信。 我将所有HTTP放在一个地方,并从其余代码中抽象出来。 在一种情况下,我想将响应内容作为流读取,但是该流的使用者与HTTP通讯发生的位置和打开的流完全隔离。 在负责HTTP通信的地方,我将处理所有HttpClient内容。 此单元测试将在Assert.IsTrue(stream.CanRead)处失败: [TestMethod] public async Task DebugStreamedContent() { Stream stream = null; // in real life the consumer of the stream is far away var client = new HttpClient(); client.BaseAddress = new Uri("https://www.google.com/", UriKind.Absolute); using (var request = new HttpRequestMessage(HttpMethod.Get, "/")) using (var response = await client.SendAsync(request)) { response.EnsureSuccessStatusCode();
  • Node.JS如何在当前范围之外设置变量(Node.JS How to set a variable outside the current scope)
    问题 我有一些我无法理解的代码,我试图使用回调返回对象数组,我有一个函数返回值,然后将其压入数组,但是我无法在函数外部访问它,我在这里做一些愚蠢的事情,但无法分辨(我对Node.JS非常陌生) for (var index in res.response.result) { var marketArray = []; (function () { var market = res.response.result[index]; createOrUpdateMarket(market, eventObj , function (err, marketObj) { marketArray.push(marketObj) console.log('The Array is %s',marketArray.length) //Returns The Array is 1.2.3..etc }); console.log('The Array is %s',marketArray.length) // Returns The Array is 0 })(); } 回答1 您在这里遇到了多个问题。 一个核心问题是要了解异步响应如何工作以及何时执行哪些代码。 但是,除此之外,您还必须学习如何在循环中管理多个异步响应,以及如何知道何时完成所有响应以及如何按顺序获取结果以及在node
  • 如何在Node.js或Javascript中将异步函数调用包装到同步函数中?(How to wrap async function calls into a sync function in Node.js or Javascript?)
    问题 假设您维护了一个暴露函数getData的库。 您的用户调用它来获取实际数据: var output = getData(); 在fs.readFileSync将数据保存在文件中,因此您可以使用Node.js内置的fs.readFileSync实现getData 。 显然, getData和fs.readFileSync都是同步功能。 有一天,您被告知将基础数据源切换到只能异步访问的仓库(例如MongoDB)。 还被告知要避免惹恼用户,不能将getData API更改为仅返回promise或要求回调参数。 您如何满足这两个要求? 使用回调/承诺的异步功能是JavasSript和Node.js的DNA。 任何不平凡的JS应用程序都可能会渗透这种编码样式。 但是这种做法很容易导致所谓的厄运回响金字塔。 更糟糕的是,如果调用链中任何调用方中的任何代码都取决于异步函数的结果,则这些代码也必须包装在回调函数中,从而在调用方上施加编码样式约束。 我不时发现有必要将async函数(通常在3rd party库中提供)封装到sync函数中,以避免大规模的全局重构。 在这个问题上寻找解决方案通常会以Node Fibers或从中衍生的npm软件包结束。 但是Fibers不能解决我面临的问题。 甚至Fibers作者提供的示例也说明了这一缺陷: ... Fiber(function() {
  • 如何检测Boost Tcp套接字何时断开连接(How to detect when a boost tcp socket disconnects)
    问题 假设我有一个套接字: std::shared_ptr<tcp::socket> socket( new tcp::socket(acceptor.get_io_service()) ); acceptor.async_accept( *socket, std::bind( handleAccept, this, std::placeholders::_1, socket, std::ref(acceptor)) ); 我将weak_ptr存储到容器中的所述套接字。 我需要这样做是因为我想允许客户端请求其他客户端的列表,以便他们可以彼此发送消息。 clients_.insert(socket); // pseudocode 然后我运行一些异步操作 socket->async_receive( boost::asio::buffer(&(*header), sizeof(Header)) , 0 , std::bind(handleReceiveHeader, this, std::placeholders::_1, std::placeholders::_2, header, socket)); 如何检测何时关闭了连接,以便可以从容器中卸下插座? clients_.erase(socket); // pseudocode 回答1
  • 同步调用异步Javascript函数(Call An Asynchronous Javascript Function Synchronously)
    问题 首先,这是一个非常特殊的情况,它以错误的方式故意将异步调用改型为一个非常同步的代码库,该代码库长成千上万行,并且当前时间不具备进行更改的能力。对的。” 它伤害了我的每一个生命,但是现实和理想常常并没有融合在一起。 我知道这很糟糕。 好的,顺便说一句,我该如何做,这样我可以: function doSomething() { var data; function callBack(d) { data = d; } myAsynchronousCall(param1, callBack); // block here and return data when the callback is finished return data; } 示例(或缺少示例)全部使用库和/或编译器,这两种库均不适用于该解决方案。 我需要一个如何使其冻结的具体示例(例如,在调用回调之前,不要离开doSomething函数)而无需冻结UI。 如果在JS中有这样的事情是可能的。 回答1 “不要告诉我应该怎么做”正确的方式”或其他任何方式” 好的。 但您确实应该以正确的方式来做... “我需要一个具体的示例来说明如何使其阻塞...而无需冻结UI。如果在JS中可能发生这种情况。” 不,如果不阻止UI,就无法阻止正在运行的JavaScript。 由于缺乏信息,很难提供解决方案
  • Swift与Objective-C的“ @synchronized”等效吗?(What is the Swift equivalent to Objective-C's “@synchronized”?)
    问题 我已经搜索过Swift书,但是找不到@synchronized的Swift版本。 如何在Swift中进行互斥? 回答1 您可以使用GCD。 它比@synchronized更为冗长,但可以替代: let serialQueue = DispatchQueue(label: "com.test.mySerialQueue") serialQueue.sync { // code } 回答2 我本人一直在寻找它,并得出结论,在此范围之内,swift尚无本地构造。 我确实根据我从Matt Bridges和其他人那里看到的一些代码组成了这个小的辅助函数。 func synced(_ lock: Any, closure: () -> ()) { objc_sync_enter(lock) closure() objc_sync_exit(lock) } 用法很简单 synced(self) { println("This is a synchronized closure") } 我发现了一个问题。 此时,将数组作为lock参数传递似乎会导致非常钝的编译器错误。 否则,尽管它似乎可以按需工作。 Bitcast requires both operands to be pointer or neither %26 = bitcast i64 %25 to %objc_object*,