• 0

هل من الممكن إنهاء thread قيد التشغيل في بايثون؟

 

أقوم بالتعلم حول تعدد المهام في بايثون وبدأت بمكتبة threading، وأصبح يمكنني أن أقوم بعمل أكثر من thread ولكن لا أعرف كيف أقوم بإيقاف thread معين. وهل يجب أن أقوم التاأكد مما إذا كان الـ thread  يقوم بعمل أمر حيوي مثل إستخدام critical resource.

كيف أقوم بإنهاء thread قيد التشغيل بطريقة آمنة؟

انشر على الشّبكات الاجتماعية


رابط هذه المساهمة
شارك على الشبكات الإجتماعية
  • 1

نعم يوجد طريقة و هي كالتالي :

import sys
import trace
import threading

#هنا نعرف صنف من نوع  Thread  
class KThread(threading.Thread):
  """هنا يرث الصنف Thread"""
  def __init__(self, *args, **keywords):
    threading.Thread.__init__(self, *args, **keywords)
    self.killed = False

  def start(self):
    """ دالة لتعريق بدأ thread """
    self.__run_backup = self.run
    self.run = self.__run      # Force the Thread to
install our trace.
    threading.Thread.start(self)

  def __run(self):
    """دالة لتشغيل التعقب لهذا ال thread."""
    sys.settrace(self.globaltrace)
    self.__run_backup()
    self.run = self.__run_backup

  def globaltrace(self, frame, why, arg):
    if why == 'call':
      return self.localtrace
    else:
      return None

  def localtrace(self, frame, why, arg):
    if self.killed:
      if why == 'line':
        raise SystemExit()
    return self.localtrace

  # هنا الدالة التي تقوم بقتله
  def kill(self):
    self.killed = True


------------------------------------------------------------------------
#طريقة الإستعمال 
------------------------------------------------------------------------


#إن كما في ملف آحر علينا إستيراد الملف الذي قمنا بخلقه 
from KThread import *


#نعرف دالة جديدة وخذخ الدالة ستقوم بعمل دوران بشكل طبيعي 
def func():
  print 'Function started'
  for i in xrange(1000000):
    pass
  print 'Function finished'

  #هنا نعرف متغير من الصنف الذي خلقناه للتحكم بال thread
  # نعطيقه الدالة ليقوم بتعقب الthread 
  #الخاص بها 
A = KThread(target=func)

# نقوم بتشغيل الدالة عن طريق Start 
A.start()
#هنا فقط لتاخير نهاية البرنامج 
for i in xrange(1000000):
  pass
#ثم هنا نقوم بقتله 
A.kill()

print 'End of main program'


Output:

  Function started

 

1 شخص أعجب بهذا

انشر على الشّبكات الاجتماعية


رابط هذه المساهمة
شارك على الشبكات الإجتماعية
  • 1

نعم يمكن، لكنها فكرة سيئة وقد تؤدي بك إلى العديد من المشاكل. لكن إليك بعض الطرق:

  1. قتل النيسب "Thread" من خلال تعريف flag بحيث عند رفعه يتم إيقافه:
    في الكود التالي، سنعرف علم (flag) وبمجرد أن نقوم برفعه ينتهي تنفيذ الدالة run ويمكن قتل النيسبth1 باستخدام th1.join.
    import time
    import threading as th
    def myfunc ():
    	while True:
    		print('The thread is still working')
        # نجعل العلم متحول عام لكي تكون التغيرات عليه عامة أي مرئية
    		global flag
        #يتم إيقاف النيسب True إذا تم رفع العلم أي إذا كان 
    		if flag:
    			break
    # في البداية نجعل العلم غير مرفوع
    flag = False
    # نعرف أول نيسب 
    # النيسب يقوم بتنفيذ الدالة السابقة
    th1 = th.Thread(target = myfunc ) 
    # تشغيل النيسب
    th1.start()
    time.sleep(1)
    # هنا مثلاً نقوم برفع العلم ليتم إيقافه
    stop_threads = True
    th1.join()
    print('thread killed')

     

  2. الطريقة الثانية هي إثارة استثناء في النيسب، من خلال استخدام الدالة PyThreadState_SetAsyncExc:
    في الكود التالي بمجرد استدعاء الدالة myexception سيتم إنهاء الدالة myfunc لأنه عندما يظهر الاستثناء سينتقل التحكم في البرنامج خارج كتلة try ويتم إنهاء الدالة. بعد ذلك نقوم باستخدام join لقتل النيسب. وفي حالة لم نقوم باستدعاء دالة رفع الاستثناء سيتم تنفيذ myfunc  بدون توقف  ولن يتم استدعاء Join  لقتل النيسب.

    import threading
    from  ctypes.pythonapi import PyThreadState_SetAsyncExc
    import time
    import ctypes
    # نيسب مع استثناء
    class exception(threading.Thread):
    	def __init__(self, name):
    		threading.Thread.__init__(self)
    		self.name = name
    	# التابع الهدف			
    	def myfunc(self):
    		try:
    			while True:
    				print('is running ' + self.name)
    		finally:
    			print('is over')
    	# دالة لإرجاع رقم الثريد		
    	def ID_(self):
    		if hasattr(self, '_thread_id'):
    			return self._thread_id
    		for id, thread in threading._active.items():
    			if thread is self:
    				return id
      # دالة لرفع استثناء
    	def myexception(self):
    		id = self.ID_()
    		e = PyThreadState_SetAsyncExc(id,
    			ctypes.py_object(SystemExit))
    		if e > 1:
    			PyThreadState_SetAsyncExc(id, 0)
          # طباعة رسالة تعبر عن أنه تمت إثارة الاستقناء
    			print('failure')
    
    th = exception('thr') # نمرر اسم النيسب
    # تشغيله
    th.start()
    time.sleep(1)
    # استدعاء دالة رفع الاستثناء ليتم إيقافه
    th.myexception()
    th.join()

     

1 شخص أعجب بهذا

انشر على الشّبكات الاجتماعية


رابط هذه المساهمة
شارك على الشبكات الإجتماعية

يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن