ভারী প্লাগ ইন চলাকালীন আমি কীভাবে কুইগিসকে "সাড়া না দিয়ে" সনাক্ত করা থেকে রক্ষা করব?


10

ব্যবহারকারীর স্থিতি সম্পর্কে অবহিত করতে আমি ফোলিং লাইন ব্যবহার করি:

iface.mainWindow().statusBar().showMessage("Status:" + str(i))

প্লাগইনটি আমার ডেটা সেটটিতে চালাতে প্রায় 2 মিনিট সময় নেয় তবে উইন্ডোজগুলি এটি "প্রতিক্রিয়া নয়" হিসাবে সনাক্ত করে এবং স্ট্যাটাস আপডেটগুলি প্রদর্শন বন্ধ করে। নতুন ব্যবহারকারীর পক্ষে এটি এতটা ভাল নয় যেহেতু দেখে মনে হচ্ছে প্রোগ্রামটি ক্র্যাশ হয়ে গেছে।

প্লাগইনের স্থিতি সম্পর্কে ব্যবহারকারী অন্ধকারে ছেড়ে না যায় বলে আশেপাশে কোনও কাজ আছে কি?

উত্তর:


13

হিসাবে নাথান ডব্লিউ তুলে ধরে যেভাবে এই কাজ করতে multithreading সঙ্গে, কিন্তু subclassing QThread সেরা অনুশীলনের নয়। এখানে দেখুন: http://mayaposch.wordpress.com/2011/11/01/how-to-really-t بيشڪ-use-qthreads-the-ful-explanation/

কীভাবে তৈরি করবেন তার উদাহরণ নীচে দেখুন QObject, তারপরে এটিতে স্থানান্তরিত করুন QThread( এটি করার সঠিক "উপায়)। এই উদাহরণটি ভেক্টর স্তরের সমস্ত বৈশিষ্ট্যের মোট ক্ষেত্রের গণনা করে (নতুন কিউজিআইএস ২.০ এপিআই ব্যবহার করে!)।

প্রথমত, আমরা "শ্রমিক" অবজেক্ট তৈরি করি যা আমাদের জন্য ভারী উত্তোলন করবে:

class Worker(QtCore.QObject):
    def __init__(self, layer, *args, **kwargs):
        QtCore.QObject.__init__(self, *args, **kwargs)
        self.layer = layer
        self.total_area = 0.0
        self.processed = 0
        self.percentage = 0
        self.abort = False

    def run(self):
        try:
            self.status.emit('Task started!')
            self.feature_count = self.layer.featureCount()
            features = self.layer.getFeatures()
            for feature in features:
                if self.abort is True:
                    self.killed.emit()
                    break
                geom = feature.geometry()
                self.total_area += geom.area()
                self.calculate_progress()
            self.status.emit('Task finished!')
        except:
            import traceback
            self.error.emit(traceback.format_exc())
            self.finished.emit(False, self.total_area)
        else:
            self.finished.emit(True, self.total_area)

    def calculate_progress(self):
        self.processed = self.processed + 1
        percentage_new = (self.processed * 100) / self.feature_count
        if percentage_new > self.percentage:
            self.percentage = percentage_new
            self.progress.emit(self.percentage)

    def kill(self):
        self.abort = True

    progress = QtCore.pyqtSignal(int)
    status = QtCore.pyqtSignal(str)
    error = QtCore.pyqtSignal(str)
    killed = QtCore.pyqtSignal()
    finished = QtCore.pyqtSignal(bool, float)

কর্মীটি ব্যবহার করতে আমাদের এটি একটি ভেক্টর স্তর দিয়ে সূচনা করতে হবে, এটি থ্রেডে সরানো হবে, কিছু সংকেত সংযুক্ত করতে হবে এবং তারপরে এটি শুরু করুন। এখানে কী চলছে তা বোঝার জন্য উপরের লিঙ্ক করা ব্লগটি দেখা ভাল ।

thread = QtCore.QThread()
worker = Worker(layer)
worker.moveToThread(thread)
thread.started.connect(worker.run)
worker.progress.connect(self.ui.progressBar)
worker.status.connect(iface.mainWindow().statusBar().showMessage)
worker.finished.connect(worker.deleteLater)
thread.finished.connect(thread.deleteLater)
worker.finished.connect(thread.quit)
thread.start()

এই উদাহরণটি কয়েকটি মূল বিষয় তুলে ধরে:

  • run()শ্রমিকের পদ্ধতির ভিতরে থাকা সমস্ত কিছুই চেষ্টা-বাদ দেওয়া বিবৃতিতে। যখন আপনার কোডটি থ্রেডের অভ্যন্তরে ক্রাশ হবে তখন এটি পুনরুদ্ধার করা কঠিন। এটি ত্রুটি সংকেতটির মাধ্যমে ট্রেসব্যাকটি নির্গত করে যা আমি সাধারণত এর সাথে সংযোগ করি QgsMessageLog
  • প্রক্রিয়াটি সফলভাবে সমাপ্ত হলে ফলাফলের সাথে সংযুক্ত পদ্ধতিটি সমাপ্ত সিগন্যালটি বলে।
  • অগ্রগতি সংকেত কেবল তখনই বলা হয় যখন প্রতিটি বৈশিষ্ট্যের জন্য একবারের চেয়ে শতাংশ সম্পূর্ণ পরিবর্তিত হয়। এটি কর্মী প্রক্রিয়াটিকে ধীরগতির করে অগ্রগতি বার আপডেট করার জন্য অনেকগুলি কলকে বাধা দেয়, যা শ্রমিককে অন্য থ্রেডে চালানোর পুরো পয়েন্টকে পরাস্ত করবে: ব্যবহারকারী ইন্টারফেস থেকে গণনা পৃথক করতে।
  • কর্মী একটি kill()পদ্ধতি প্রয়োগ করে , যা কার্যটি নিখুঁতভাবে শেষ করতে দেয়। চেষ্টা করুন এবং terminate()পদ্ধতিটি ব্যবহার না করে QThread- খারাপ জিনিসগুলি ঘটতে পারে!

আপনার প্লাগইন কাঠামোর কোথাও আপনার threadএবং workerঅবজেক্টের ট্র্যাক রাখতে ভুলবেন না । না করলে কিউটি রাগান্বিত হয়। এটি করার সবচেয়ে সহজ উপায় হ'ল আপনি যখন এগুলি তৈরি করবেন তখন তা আপনার ডায়লগে সংরক্ষণ করুন, যেমন:

thread = self.thread = QtCore.QThread()
worker = self.worker = Worker(layer)

অথবা আপনি Qt কে কিউথ্রেডের মালিকানা নিতে দিতে পারেন:

thread = QtCore.QThread(self)

এই টেমপ্লেটটি একসাথে রাখার জন্য সমস্ত টিউটোরিয়াল খনন করতে আমার অনেক সময় লেগেছে, তবে তখন থেকে আমি সমস্ত জায়গা জুড়ে এটি পুনরায় ব্যবহার করছি।


আপনাকে ধন্যবাদ যা আমি ঠিক তাই খুঁজছিলাম এবং এটি খুব সহায়ক ছিল! আমি আই সি # থ্রেডে অভ্যস্ত কিন্তু অজগর হিসাবে এটি ভাবেনি।
জোহান হল্টবি

হ্যাঁ এটি সঠিক উপায়।
নাথান ডাব্লু

1
"স্ব" থাকা উচিত। "বৈশিষ্ট্য = স্তর.get ফিচারস ()" এ লেয়ারের সামনে? -> "বৈশিষ্ট্যগুলি = স্ব.লায়ার.জেটফিটচার্স ()"
হাভার্ড টিভাইট

@ হ্যাভার্ডটিভাইট আপনি সঠিক আছেন। আমি উত্তরে কোডটি ঠিক করেছি।
স্নোরফলোরপাগাস

আমি লিখছি এমন একটি প্রসেসিং স্ক্রিপ্টের জন্য এই প্যাটার্নটি অনুসরণ করার চেষ্টা করছি এবং এটি কাজ করতে আমার সমস্যা হচ্ছে। আমি এই উদাহরণটি একটি স্ক্রিপ্ট ফাইলে অনুলিপি করার চেষ্টা করেছি, প্রয়োজনীয় আমদানি বিবৃতি যুক্ত করেছি এবং worker.progress.connect(self.ui.progressBar)অন্য কোনও কিছুর পরিবর্তিত করেছি , তবে প্রতিবারই আমি যখন এটি চালাচ্ছি তখন কিগিস-বিন ক্রাশ হচ্ছে। পাইথন কোড বা কিউগিস ডিবাগ করার আমার কোনও অভিজ্ঞতা নেই। আমি যা পাচ্ছি তা Access violation reading location 0x0000000000000008তাই মনে হচ্ছে কিছু শূন্য। এমন কোনও সেট আপ কোড রয়েছে যা প্রসেসিং স্ক্রিপ্টে এটি ব্যবহার করতে সক্ষম হারাচ্ছে?
টিজে রকফেলার

4

এটি করার একমাত্র আসল উপায় হ'ল মাল্টিথ্রেডিং।

class MyLongRunningStuff(QThread):
    progressReport = pyqtSignal(str)
    def __init__(self):
       QThread.__init__(self)

    def run(self):
       # do your long runnning thing
       self.progressReport.emit("I just did X")

 thread = MyLongRunningStuff()
 thread.progressReport.connect(self.updatetheuimethod)
 thread.start()

কিছু অতিরিক্ত পড়া http://joplaete.wordpress.com/2010/07/21/threading-with-pyqt4/

দ্রষ্টব্য কিছু লোকেরা কিউথ্রেডের উত্তরাধিকার সূত্রে পছন্দ করে না এবং সম্ভবত এটি এটি করার "সঠিক" উপায় নয় তবে এটি কাজ করে ....


:) এটি করার মতো দুর্দান্ত ময়লা লাগে। কিছু সময় শৈলী প্রয়োজন হয় না। এই সময়ের জন্য (পাইকার্টে প্রথম) আমি মনে করি যে আমি সি # তে অভ্যস্ত থাকায় আমি সঠিক পথে যাব।
জোহান হল্টবি

2
এটি কোনও নোংরা উপায় নয়, এটি করার প্রাচীন উপায় ছিল।
নাথান ডাব্লু

2

এই প্রশ্নটি তুলনামূলকভাবে পুরান হওয়ায় এটি একটি আপডেটের দাবি রাখে। কিউজিআইএস 3 এর সাথে কিউগসটাস্ক.ফ্রমফংশন (), কিগসপ্রসেসিংএলজিআরনারটাস্ক () এবং কিউজসপ্লিকেশন.টাস্ক ম্যানেজার ()। অ্যাডটাস্ক () রয়েছে approach

এর সম্পর্কে আরও উদাহরণস্বরূপ মারকো বার্নাসোচি দ্বারা পাইকিজিআইএস 3-তে থ্রেড ব্যবহার করা

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.