2010-08-17 15 views
7

Bükümle ilgili anladığım kadarıyla, reaktör ipliklerinde hiçbir şey çalışmaz. Tüm engelleme aktiviteleri, diğer iş parçacıklarına devredilmeli ve geri çağrılar, tamamlandığında reaktör iş parçacığına geri gönderilmelidir.twisted + gtk: GUI şeylerini iş parçacığında mı, yoksa reaktör dizisinde mi çalıştırmalıyım?

Bu, aynı zamanda bazı şeyler için de geçerli midir? Örneğin, bağlantı başarısız olursa "bağlantı başarısız" mesajını görüntülemek istiyorum. Yapmak mı:

def connectionFailed(self, reason): 
    dlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, 
         buttons=gtk.BUTTONS_CLOSE, 
         message_format="Could not connect to server:\n%s" % (
          reason.getErrorMessage())) 
    dlg.run() 

ya:

def connectionFailed(self, reason): 
    dlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, 
         buttons=gtk.BUTTONS_CLOSE, 
         message_format="Could not connect to server:\n%s" % (
          reason.getErrorMessage())) 
    reactor.callInThread(dlg.run) 

ya:

def connectionFailed(self, reason): 
    def bloogedy(): 
     dlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, 
          buttons=gtk.BUTTONS_CLOSE, 
          message_format="Could not connect to server:\n%s" % (
           reason.getErrorMessage())) 
     dlg.run() 
    reactor.callInThread(bloogedy) 

?

DÜZENLEME: Ooh tamam, ikinci iki gerçekten berbat. Yani sanırım cevap ilk. O zaman sorum şu: neden? Bu reaktör iplik engellenir gibi görünüyor.

cevap

10

Sorununuzun aslında iş parçacığı ve GUI'lerle ilgisi yoktur. Her zaman Twisted ve GTK'yi aynı konudan kullanmalısınız: aksi takdirde yapmanız gerekmez.

Sorununuz, gtk.Dialog.run() kullanıyor olmanızdır. Bu, asla kullanmamalısınız, Twisted olsun ya da olmasın bir API. Geçerli olay işleyicinizin engellenmesine neden olan yeniden giriş yapan bir ana döngü çalıştırır, ancak diğer olay işleyicilerinin yığından bir katman yürütmesine izin verir. GTK yeniden giriş yapan ana döngüler için mükemmel bir desteğe sahip, ancak Twisted yapmıyor (ve bunu söylemiyorum çünkü dediğim gibi, onları kullanmamalısınız).

MessageDialog.run zaten bir iş parçacığında çalışmaz, bu nedenle aslında bu seçeneğe sahip değilsiniz. Uygulamanızın garip davranmasına veya çökmesine neden olabilecek tahmin edilemez davranışlara neden olur. GTK'nın dişler için iyi desteği var, ama hiçbir zaman bir iş parçacığıyla asla yapmamanız gereken şeyler var, çünkü hiçbir anlamı yok, ve bu onlardan biri.

Herhangi bir işlem yapmayan bir kodla uğraşıyorsanız, ancak bir şeylerin gerçekleşmesini beklemek istiyorsanız (kullanıcının bir iletişim kutusundaki bir düğmeyi beklemesini beklemek gibi), Deferred döndüren işlevleri kullanmalısınız , konu değil. Olduğu gibi, gtk.Dialog s, "response" yanıt verdikleri noktada bir sinyal yayar. Mesajınızı bir iletişim kutusuyla görüntüleyen çok basit bir işlev oluşturmak için bunu kullanabilirsiniz ve tamamlandığında Deferred değerini döndürür. İşte bir örnek:

def showMessage(text): 
    mdlg = gtk.MessageDialog(type=gtk.MESSAGE_INFO, 
          buttons=gtk.BUTTONS_CLOSE, 
          message_format=text) 
    result = Deferred() 
    def response(dialog, response_id): 
     mdlg.destroy() 
     result.callback(response_id) 
     return False 
    mdlg.connect("response", response) 
    mdlg.show_all() 
    return result 
+0

ah parçasında Gtk + 'ı başlatan kodu içerecek şekilde düzenledim. 'Run() 'ile bir ilgisi olduğunu bir mırıltı vardı. ertelenen kesinlikle gitmek için yoldur. – Claudiu

0

Gtk + deneyimimden en iyi seçenek, GUI'yi ayrı bir iş parçacığında çalıştırmaktır. Gtk + ana döngüsünde (idle_add işlevi aracılığıyla) işlevler çalıştırarak GUI iş parçacığı ile iletişim kurabilirsiniz. Reaktör hakkında hiçbir şey bilmiyorum, ama örneklerinden, GUI'den aynı şekilde iletişim kurmanın mümkün olduğu anlaşılıyor.

Örneğin, bu (üzgünüm, kod test etmedim) gibi:

def connectionFailed(self, reason): 
    def frob(): 
     dlg = gtk.MessageDialog(type=gtk.MESSAGE_ERROR, 
          buttons=gtk.BUTTONS_CLOSE, 
          message_format="Could not connect to server:\n%s" % (
           reason.getErrorMessage())) 
     dlg.run() 
    gobject.idle_add(frob) 

(bu kodun yanında gtk.main kendi iş parçacığı üzerinde çalıştırmak gerekecektir)

Bu Gtk + iş parçacığında frob işlevini çalıştıracak ve reaktör dizisini engellemeyecek.

Bu ayrı bir konu GTK + başlayacak: Eğer bazı karmaşık GUI etkileşimleri gerekiyorsa

import threading 
import pygtk 
pygtk.require('2.0') 
import gtk 
import gobject 
def gtk_thread(): 
    gtk.main() 
threading.Thread(target=gtk_thread) 

, sen continuation-passing style

Edit kullanarak programlamak gerekir: Ayrı içinde GTK + çalışan örneğini eklendi konu

+0

GUI'yi farklı bir iş parçacığında nasıl çalıştırırım? Ben sadece gtk2reactor.install() 'i yaptım ve bu reaktörü kullandım. Ben bu olmadan twisted + gtk kullanmaya çalıştığımda çok büyük sorunlar yaşadım. – Claudiu

+0

İletiyi, daha anlamlı yapan –

0

tavsiye ve desteklenmeyen olmasa da, Twisted 10.x ile aşağıdaki kod gtk.main() kullanmaya devam etmek mümkün hale getirecek anlaşılmaktadır/dialog.run()

gobject.idle_add(lambda *x: reactor.runUntilCurrent()) 
    reactor.startRunning()  
    dialog.run() 
İlgili konular