Юля: Передача данных между сопрограммами (задачами)

Я пытался заставить две задачи (сопрограммы) взаимодействовать, но безуспешно. Ниже то, что у меня есть. Я никогда не вижу printlns ни из функций источника, ни из функций приемника, и кажется, что вызов wait () зависает навсегда. Я также попытался сделать задачу p (источник) глобальной переменной, вместо того, чтобы передавать ее в раковину () в качестве аргумента, но это тоже, похоже, не работает (даже когда я объявляю ее внутри синке () как глобальную.

Я обнаружил, что это то, что я могу очень легко делать с каналами и горутинами в Go.

Я также экспериментировал с вызовом yieldto () внутри функций source () иink (), но, похоже, я все еще захожу в тупик.

У кого-нибудь есть пример того, как несколько задач каким-либо образом обмениваются данными? В идеале у меня был бы конвейер или длинная цепочка задач.

Заранее спасибо за помощь.

println("Hello")

function source()
  println("source start")
  produce("start")
  produce("stop")
end

function sink(p::Task)
  println("sink start")
  println(consume(p))
  println(consume(p))
end


a = Task( source )
b = Task( () -> sink(a)   )

wait(b)
wait(a)

println("Goodbye")

person Richard Palmer    schedule 22.04.2014    source источник


Ответы (1)


В Julia создание задачи не включает ее в расписание автоматически. Функция ожидания также не входит в расписание, поэтому вы попадаете в тупик. Это большое отличие от Go, где оператор go берет на себя все планирование за вас. В julia вам нужно проделать еще немного работы. В частности, используйте макросы @sync и @async, чтобы упростить задачу.

@sync begin # @sync will wait for all the contained tasks to terminate.
   a = @async source() # @async will create and schedule a task for you automatically
   @async sink(a)
 end

Однако вы заметите, что это тоже не заканчивается. Все отпечатки выполняются, но задача не прекращается. Причина в том, что @sync ожидает завершения задачи a, но задача a не была запланирована. Добавьте окончательное потребление или расписание к вашей функции приемника, чтобы заставить задачу a быть запланированной в последний раз, чтобы она могла завершиться. Или еще лучше используйте цикл for для задачи, чтобы вы всегда ее исчерпывали.

println("Hello")

function source()
  println("source start")
  produce("start")
  produce("stop")
  println("source end")
end

function sink(p::Task)
  println("sink start")
  for s in p
    println(s)
  end
  println("sink end")
end

@sync begin
   a = @async source()
   @async sink(a)
 end

println("Goodbye")

Задачи Джулии планируются совместно, что в основном означает, что вы должны обеспечить планирование каждой задачи самостоятельно. Среда выполнения не сделает этого за вас. К счастью, макросы @sync и @async делают большую часть этого за вас.

person Jeremy Wall    schedule 22.04.2014
comment
Здорово! Спасибо за четкий ответ. Я вижу, что julia дает гораздо более точный контроль над сопрограммами. Я ценю вашу помощь. - person Richard Palmer; 22.04.2014