اذهب إلى المحتوى

السؤال

نشر

 

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

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

Recommended Posts

  • 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. قتل النيسب "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()

     

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...