Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Tkinter + Thread = trouble, смотрите! оно виснет! 
:(
    Опции темы
setq
Дата 12.7.2005, 13:13 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











я хочу написать приложение, в котором пользователю придётся работать с различными окнами. большую часть времени на экране будет только одно из них, но не исключён вариант, что пользователь захочет работать со всеми сразу.

поэтому я подумал, что неплохо было бы сначала создать экземпляры окон а затем запустить их mainloop () в разных потоках.

следующий пробный код виснет по неизвестной мне причине:
Код
from Tkinter import *
from threading import Thread

class MyTk (Tk) :
    def __init__ (self) :
        Tk.__init__ (self)
        Button (self, text='CLOSE ME', command=self.destroy).pack ()

if __name__ == '__main__' :
    ts = [Thread (None, MyTk ().mainloop),
          Thread (None, MyTk ().mainloop),
          Thread (None, MyTk ().mainloop)]
    [t.start () for t in ts]
    [t.join ()  for t in ts]
первый раз всё три окна появляются на экране, но при последующих запусках наблюдаются только рамки от окон. внутренности не прорисовываются... помогите пожалуйста.
  Вверх
grock
Дата 13.9.2005, 08:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 3.8.2005
Где: Санкт - Петербург

Репутация: 1
Всего: 1



кстати, нашел одну фишку недавно, если создать несколько объектов окон ( Tk() ), апотом в одном из них вызвать mainloop(), как ты думешь, что случиться ?
PM MAIL   Вверх
setq
Дата 13.9.2005, 10:10 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











ушёл ставить эксперимент





Добавлено @ 10:17
о майн дог! %) за что?!

так ну надо разобраться...

Это сообщение отредактировал(а) setq - 13.9.2005, 10:18
  Вверх
grock
Дата 13.9.2005, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 3.8.2005
Где: Санкт - Петербург

Репутация: 1
Всего: 1



вот такой вот глюкодром smile
PM MAIL   Вверх
setq
Дата 13.9.2005, 11:56 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











ага. скачал исходники и залез в _tkinter.c:
Код
/* The threading situation is complicated.  Tcl is not thread-safe, except
   when configured with --enable-threads.
   So we need to use a lock around all uses of Tcl.  Previously, the Python
   interpreter lock was used for this.  However, this causes problems when
   other Python threads need to run while Tcl is blocked waiting for events.

   To solve this problem, a separate lock for Tcl is introduced.  Holding it
   is incompatible with holding Python's interpreter lock.  The following four
   macros manipulate both locks together.

   ENTER_TCL and LEAVE_TCL are brackets, just like Py_BEGIN_ALLOW_THREADS and
   Py_END_ALLOW_THREADS.  They should be used whenever a call into Tcl is made
   that could call an event handler, or otherwise affect the state of a Tcl
   interpreter.  These assume that the surrounding code has the Python
   interpreter lock; inside the brackets, the Python interpreter lock has been
   released and the lock for Tcl has been acquired.

   Sometimes, it is necessary to have both the Python lock and the Tcl lock.
   (For example, when transferring data from the Tcl interpreter result to a
   Python string object.)  This can be done by using different macros to close
   the ENTER_TCL block: ENTER_OVERLAP reacquires the Python lock (and restores
   the thread state) but doesn't release the Tcl lock; LEAVE_OVERLAP_TCL
   releases the Tcl lock.

   By contrast, ENTER_PYTHON and LEAVE_PYTHON are used in Tcl event
   handlers when the handler needs to use Python.  Such event handlers are
   entered while the lock for Tcl is held; the event handler presumably needs
   to use Python.  ENTER_PYTHON releases the lock for Tcl and acquires
   the Python interpreter lock, restoring the appropriate thread state, and
   LEAVE_PYTHON releases the Python interpreter lock and re-acquires the lock
   for Tcl.  It is okay for ENTER_TCL/LEAVE_TCL pairs to be contained inside
   the code between ENTER_PYTHON and LEAVE_PYTHON.

   These locks expand to several statements and brackets; they should not be
   used in branches of if statements and the like.

   If Tcl is threaded, this approach won't work anymore. The Tcl interpreter is
   only valid in the thread that created it, and all Tk activity must happen in this
   thread, also. That means that the mainloop must be invoked in the thread that
   created the interpreter. Invoking commands from other threads is possible;
   _tkinter will queue an event for the interpreter thread, which will then
   execute the command and pass back the result. If the main thread is not in the
   mainloop, and invoking commands causes an exception; if the main loop is running
   but not processing events, the command invocation will block.

   In addition, for a threaded Tcl, a single global tcl_tstate won't be sufficient
   anymore, since multiple Tcl interpreters may simultaneously dispatch in different
   threads. So we use the Tcl TLS API.

*/




если я правильно всё перевёл, то это приговор.






Это сообщение отредактировал(а) setq - 13.9.2005, 11:57
  Вверх
grock
Дата 13.9.2005, 12:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 3.8.2005
Где: Санкт - Петербург

Репутация: 1
Всего: 1



Есть вариант, делать самому safe для threads, это использование очередей :
http://aspn.activestate.com/ASPN/Cookbook/...on/Recipe/82965 - пример

почему нельзя использовать мой код, он ведь работает нормально без очередей (хотя, почему-то не везде такой подход прокатывает smile ) ? :

Код

from Tkinter import * 
import time 
from threading import Thread 
import random 

def thr(): 

    while 1: 
        time.sleep(rand.random() * 0.3) 
        e.insert(END,str(rand.random()) + '\n') 


rand = random.Random() 
t = Thread(target = thr) 
t.start() 
w = Tk() 
global e 
e = Text(w) 
e.pack() 
w.mainloop() 


PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Python: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0556 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.