0

In my first attempt, I tried, failed, learned, and came back with the following attempt.

I have a text file with the names parsed with commas that looks like this:

Ann Marie,Smith,ams@companyname.com

The list could have over 100+ names in it. I left out the code that generates all the other GUI components to focus on loading the combobox and the items.

I'm trying to read a text and load the data into a combobox without blocking the main thread. I consulted a textbook and Pythons documentation, and this is what I came up with.

Question:

In my def read_employees(self,read_file): I return a list of the data I read. I'm aware that list isn't thread-safe, is it okay in the way i used it here?

Same goes for the setting of the combobox in def textfilemanage(self): I set the combobox in that method by doing, self.combo = wx.ComboBox(self.panel, choices=data). Is that okay?

import wx
import concurrent.futures

class Mywin(wx.Frame):

    def __init__(self, parent, title):
        super(Mywin, self).__init__(parent, title=title, size=(300, 200))

        self.panel = wx.Panel(self)
        box = wx.BoxSizer(wx.VERTICAL)
        self.textfilemanage()
        self.label = wx.StaticText(self.panel, label="Your choice:", style=wx.ALIGN_CENTRE)
        box.Add(self.label, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 20)
        cblbl = wx.StaticText(self.panel, label="Combo box", style=wx.ALIGN_CENTRE)

        box.Add(cblbl, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5)

        box.Add(self.combo, 1, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5)
        chlbl = wx.StaticText(self.panel, label="Choice control", style=wx.ALIGN_CENTRE)
        box.AddStretchSpacer()
        self.combo.Bind(wx.EVT_COMBOBOX, self.OnCombo)

        self.panel.SetSizer(box)
        self.Centre()
        self.Show()

    def read_employees(self,read_file):
        emp_list = []
        with open(read_file) as f_obj:
            for line in f_obj:
                emp_list.append(line)
        return emp_list

    def textfilemanage(self):
        filename = 'employees.txt'

        with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
            future_to_read = {executor.submit(self.read_employees, filename)}
            for future in concurrent.futures.as_completed(future_to_read):
                data = future.result()

        self.combo = wx.ComboBox(self.panel, choices=data)

    def OnCombo(self, event):
        self.label.SetLabel("You selected" + self.combo.GetValue() + " from Combobox")


app = wx.App()
Mywin(None, 'ComboBox and Choice demo')
app.MainLoop()

1 Answers1

0

The for-loop in textfilemanage() waits until the thread finishes so the different thread is useless in the code.

Instead:

Create the empty combobox in __init__ (needed for layouting) and assign it to self.combo

In textfilemanage() start the thread but don't wait for it.

In read_employees() replace the final return statement by

wx.CallAfter(self.combo.Append, emp_list)

or

wx.CallAfter(self.combo.AppendItems, emp_list)

(it depends on the wxPython version which variant is accepted)

Michael Butscher
  • 10,028
  • 4
  • 24
  • 25
  • If I was returning something, then I would have to wait by blocking, right? –  Nov 09 '17 at 03:20
  • @S.R. You can wait for the result or from time to time ask the `Future` if it is `done()` (and do something else inbetween) and then get the `result()` – Michael Butscher Nov 09 '17 at 13:00
  • You don't need to provide code(it will go beyond the scope of the question) but what method do read up on to ask the `Future` if it is `done()` from time to time? Using the `done()`, and boolean value? –  Nov 09 '17 at 13:24
  • @S.R. Yes, I wanted to be creative :-) and integrated the necessary methods in the text. Just call `done()` on the future from time to time and if it returns `True`, the function called in the separate thread terminated and you can call `result()` to retrieve the return value of the function. – Michael Butscher Nov 09 '17 at 13:51
  • I have a follow up question, and so far no one has answered, could you possibly help? https://stackoverflow.com/questions/47290677/when-to-call-thread-join-in-a-gui-application –  Nov 15 '17 at 02:03
  • I asked another [question](https://stackoverflow.com/questions/54282226/trying-to-undestand-why-creating-and-manipulating-futures-a-bad-practice?noredirect=1&lq=1) about async and futures, but still don't have a proper answer, could you help? –  Jan 21 '19 at 16:31