Note that there are some explanatory texts on larger screens.

plurals
  1. POThreading and Queuing with Functions
    primarykey
    data
    text
    <p>I've been having difficulty with multithreading and tkinter. <code>slxl</code> is a module I use that works and its functions do not return values (just to make sure there is no confusion.) </p> <p>Here is code that <strong>has</strong> worked in the past: </p> <pre><code> #relevant tkinter code def create_widgets(): self.updatebttn = Button(self, text='Auto Update', command=self.spawnthread) self.updatebttn.grid(row=1, column=0, sticky=N) self.progressbar = Progressbar(self, orient='horizontal', length=300, mode='determinate') self.progressbar.grid(row=1, column=1, sticky=W) self.progressbar["maximum"] = (slxl.sizeFinder()) * 1.1 def spawnthread(self): self.updatebttn.config(state="disabled") self.thread = ThreadedClient1(self.queue) self.thread.start() self.periodiccall() def periodiccall(self): if self.thread.is_alive(): self.after(100, self.periodiccall) self.progressbar.step(500) else: self.updatebttn.config(state="active") self.progressbar.stop() class ThreadedClient1(threading.Thread): def __init__(self, queue): threading.Thread.__init__(self) self.queue = queue def run(self): time.sleep(1) importer = slxl.runImportAndCoordAdder() self.queue.put(importer) </code></pre> <p>The thing is, I would like ThreadedClient1 to be able to take the function it's putting into the queue, in this case <code>slxl.runImportAndCoordAdder()</code> as an argument, since I use <code>ThreadedClient</code> more than once with different functions (I have an identical use of it later on in the program only with a different function) and I don't like having <code>ThreadedClient1</code> and <code>ThreadedClient2</code>, the only difference being <code>importer =</code> different functions. </p> <p>I did attempt a solution with lambda as such: </p> <pre><code>def spawnthread(self): self.updatebttn.config(state="disabled") self.thread = ThreadedClient1(self.queue, lambda: slxl.runImportAndCoordAdder()) self.thread.start() self.periodiccall() #periodic call is the same class ThreadedClient1(threading.Thread): def __init__(self, queue, fcn): threading.Thread.__init__(self) self.queue = queue self.fcn = fcn def run(self): time.sleep(1) self.queue.put(lambda: self.fcn) </code></pre> <p>This did not work, as it ignored the function I'm interested in, budged the progressbar a bit/disabled and enabled the button, then ended. </p> <p>What am I doing wrong?</p> <p><strong>Edit:</strong> Problem solved. Another arose, though. I'd like to transfer <code>spawnthread</code>, <code>periodiccall</code>, and <code>ThreadedClient</code> to a widget template module I have and generalize them so I can use them easily. I did this: </p> <pre><code>def spawnthread(self, widget): widget.config(state="disabled") self.thread = ThreadedClient1(self.queue) self.thread.start() self.periodiccall() </code></pre> <p>Which worked, until I tried to generalize <code>periodiccall</code> as well. </p> <pre><code> #... self.periodiccall(widget=widget) def periodiccall(self, widget=None): if self.thread.is_alive(): self.after(100, self.periodiccall) self.progressbar.step(500) #print widget else: widget.config(state="active") self.progressbar.stop() </code></pre> <p>I popped in the <code>print widget</code> to see what was going on since I kept getting an attribute error. What appears to be happening is that the first time it runs though the function it knows what "widget" is and then it turns into in the <code>None</code> I wanted it to be by calling <code>self.periodiccall</code> in the <code>after</code> statement. At least, that's what I think is happening. How do I remove this error and make widget a variable in this recursive function? </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload