سؤال

إذا أفعل

Process.fork do 
  x 
end 

وكيف لي أن أعرف ما عاد X (على سبيل المثال الحقيقية / FASE / سلسلة)؟

و(الكتابة إلى ملف / قاعدة بيانات ليست خيارا ...)

هل كانت مفيدة؟

المحلول 3

وأنا ملفوفة كل الحلول وجدت على طول الطريق (بعض المشاكل الأخرى مثل خروج المستخدم + الأنابيب-مخازن) في روبي بالتوازي جوهرة . الآن فمن السهل كما:

results = Parallel.map([1,2,3],:in_processes=>4) do |i|
  execute_something(i)
end

أو

results = Parallel.map([1,2,3],:in_threads=>4) do |i|
  execute_something(i)
end

نصائح أخرى

وفعلا كان لدينا فقط للتعامل مع هذه المشكلة في <لأ href = "http://github.com/rails/rails/blob/eea7b5db1db5d7e6020c5bcb6b4d85afcbc2e696/activesupport/lib/active_support/testing/isolation.rb#L37-54" يختلط = "noreferrer"> القضبان العزلة اختبار . نشرت لي عن ذلك بعض على بلدي بلوق .

وأساسا، ما تريد القيام به هو فتح الأنابيب في الوالدين والطفل، ويكون الطفل الكتابة إلى الأنابيب. وإليك طريقة بسيطة لتشغيل محتويات كتلة في عملية طفل ونعود النتيجة:

def do_in_child
  read, write = IO.pipe

  pid = fork do
    read.close
    result = yield
    Marshal.dump(result, write)
    exit!(0) # skips exit handlers.
  end

  write.close
  result = read.read
  Process.wait(pid)
  raise "child failed" if result.empty?
  Marshal.load(result)
end

وثم هل يمكن تشغيل:

do_in_child do
  require "some_polluting_library"
  SomePollutingLibrary.some_operation
end

لاحظ أنه إذا كنت تفعل تتطلب في الطفل، سوف لا يكون لديك الوصول إلى هذه المكتبة في الأصل، وبالتالي لا يمكنك إرجاع كائن من هذا النوع باستخدام هذا الأسلوب. ومع ذلك، يمكن إرجاع أي نوع التي تتوفر في كليهما.

ونلاحظ أيضا أن الكثير من التفاصيل هنا (read.close، Process.wait2(pid)) هي تفاصيل معظمهم تنظيف الغرف، حتى إذا كنت تستخدم هذا الكثير ربما يجب عليك الانتقال من ذلك إلى مكتبة الأداة التي يمكنك إعادة استخدامها.

وأخيرا، لاحظ أن هذا لن يعمل على ويندوز أو JRuby، لأنها لا تدعم التفرع.

وشكرا لجميع الأجوبة، وحصلت لي حل وتشغيلها، لا تزال بحاجة لمعرفة كيفية التعامل مع بيئات غير التفرع، لكنه الآن يعمل:)

read, write = IO.pipe
Process.fork do
  write.puts "test"
end
Process.fork do
  write.puts 'test 2'
end

Process.wait
Process.wait

write.close
puts read.read
read.close

ويمكنك أن ترى ذلك في العمل @ parallel_specs القضبان المساعد

نعم، يمكنك إنشاء فرعي أو جانبي لتنفيذ كتلة الداخل.

جوهرة aw :

Aw.fork! { 6 * 7 } # => 42

وبطبيعة الحال، فإنه يمنع من الآثار الجانبية:

arr = ['foo']
Aw.fork! { arr << 'FUU' } # => ["foo", "FUU"]
arr # => ["foo"]

واستنادا إلى وثائق:

<اقتباس فقرة>   

إذا تم تحديد كتلة، يتم تشغيل تلك الكتلة في فرعي أو جانبي، وفرعي أو جانبي ينهي مع حالة الصفر.

وحتى إذا كنت اسميها مع كتلة، فإنها ترجع 0. وإلا، فإنه يعمل في الأساس نفس استدعاء نظام fork() على يونيكس (الوالد يتلقى PID العملية الجديدة، والطفل يتلقى nil).

ووالاتصالات شوكة بين عمليتين يونكس هو أساسا رمز الإرجاع وليس أكثر. ومع ذلك، يمكن فتح filedescriptor بين العمليتين وتمرير البيانات بين العمليات على هذا filedescriptor: هذا هو العادية يونكس طريق أنبوب

إذا كنت تمر Marshal.dump () وMarshal.load () القيم، يمكن بسهولة تمرير الكائنات روبي بين هذه العمليات روبي.

ويمكنك استخدام الذاكرة المشتركة أن تفعل هذا إذا كان الطفل يحتاج فقط إلى أن قطعة صغيرة من التعليمات البرمجية روبي. وشيء من هذا القبيل ما يلي يعمل:

str = 'from parent'

Thread.new do
  str = 'from child'
end

sleep(1)

puts str    # outputs "from child"

والتزامن يمكن أن تكون خادعة إلى حد ما، رغم ذلك، والوصول إلى الذاكرة المشتركة بهذه الطريقة هو جزء كبير من السبب - أي وقت كنت قد حصلت على متغير وعملية أخرى قد يتغير بها من تحتك، يجب أن تكون حذرا جدا. بدلا من ذلك، يمكنك استخدام الأنابيب، والتي هي أكثر تعقيدا ولكن ربما أكثر أمانا لأي لكن الرمز الأكثر تافهة، ويمكن أيضا أن تستخدم لتشغيل أي أمر تعسفي. وهنا على سبيل المثال، مباشرة من rdoc لIO.popen:

f = IO.popen("uname")
p f.readlines     # outputs "Darwin", at least on my box  :-)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top