Why does the interpreted order seem different from what I expect?
I have a problem that I have not faced before:
It seems that the order of interpretation in my program is somehow different from what I expect. I have written a small Twitter client. It takes a few seconds for my program to actually post a tweet after I click the "GO" button (which can also be activated by hitting ENTER on the keyboard). I don't want to click multiple times within this time period thinking that I hadn't clicked it the first time. Therefore, when the button is clicked, I would like the label text to display something that tells me that the button has been clicked.
I have implemented this message by altering the label text before I send the tweet across. However, for some reason, the message does not display until the tweet has been attempted. But since I have a confirmation message after the tweet, I never get to see this message and my original problem goes unsolved.
I would really appreciate any help. Here is the relevant code:
class SimpleTextBoxForm(Form):
def __init__(self):
# set window properties
self.Text = "Tweeter"
self.Width = 235
self.Height = 250
#tweet away
self.label = Label()
self.label.Text = "Tweet Away..."
self.label.Location = Point(10, 10)
self.label.Height = 25
self.label.Width = 200
#get the tweet
self.tweetBox = TextBox()
self.tweetBox.Location = Point(10, 45)
self.tweetBox.Width = 200
self.tweetBox.Height = 60
self.tweetBox.Multiline = True
self.tweetBox.WordWrap = True
self.tweetBox.MaxLength = 140;
#ask for the login ID
self.askLogin = Label()
self.askLogin.Text = "Login:"
self.askLogin.Location = Point(10, 120)
self.askLogin.Height = 20
self.askLogin.Width = 60
self.login = TextBox()
self.login.Text= ""
self.login.Location = Point(80, 120)
self.login.Height = 40
self.login.Width = 100
#ask for the password
self.askPass = Label()
self.askPass.Text = "Password:"
self.askPass.Location = Point(10, 150)
self.askPass.Height = 20
self.askPass.Width = 60
# display password box with character hiding
self.password = TextBox()
self.password.Location = Point(80, 150)
self.password.PasswordChar = "x"
self.password.Height = 40
self.password.Width = 100
#submit button
self.button1 = Button()
self.button1.Text = 'Tweet'
self.button1.Location = Point(10, 180)
self.button1.Click += self.update
self.AcceptButton = self.button1
#pack all the elements of the form
self.Controls.Add(self.label)
self.Controls.Add(self.tweetBox)
self.Controls.Add(self.askLogin)
self.Controls.Add(self.login)
self.Controls.Add(self.askPass)
self.Controls.Add(self.password)
self.Controls.Add(self.button1)
def update(self, sender, event):
if not self.password.Text:
self.label.Text = "You forgot to enter your password..."
else:
self.tweet(self.tweetBox.Text, self.login.Text, self.password.Text)
def tweet(self, msg, login, password):
self.label.Text = "Attempting Tweet..." # this should be executed before sending the tweet is attempted. But this seems to be executed only after the try block
try:
succ开发者_高级运维ess = 'Tweet successfully completed... yay!\n' + 'At: ' + time.asctime().split()[3]
ServicePointManager.Expect100Continue = False
Twitter().UpdateAsXML(login, password, msg)
except:
error = 'Unhandled Exception. Tweet unsuccessful'
self.label.Text = error
else:
self.label.Text = success
self.tweetBox.Text = ""
The interpretation/execution order is correct, but what's happening is that you're not giving Windows Forms time to action the label text change before going into your blocking Web request. Basically setting the label.Text posts a message to the form requesting that the text be changed, but it won't be actioned until you return from the event handler (and the form starts pumping messages again). At the moment, you're not returning from the event handler until the Web request is finished, at which point of course (a) the message is irrelevant and (b) the label.Text instantly gets overwritten by the next queued-up update.
The solution is to do your Web service request in a background thread, for example by using the BackgroundWorker component. This allows the form to start pumping messages again immediately, while the background thread runs, so the label will be updated immediately. Note however that this also means the rest of the form will be responsive, which means the user could push the button again, so you may want to disable things as well as just updating the status.
精彩评论