为什么我首次尝试更改此代码不中的按钮文字,而第三次尝试有效?
我的用户必须在串口连接时等待几秒钟。在那之后,我想提醒他他已经连接(第二次尝试可能会导致问题)。
我想让他知道事情还可以,所以他不会想“呃”并点击两次。
失败。文本更改永远不会出现。
好的,为什么按钮文本中的第三个更改有效,但第一个没有?我不知道第二个是否有效。
/***********************************************************************
* Button: Connect Port *
***********************************************************************/
private void TheConnectPortButton_Click(object sender, EventArgs e)
{
string OldText = TheConnectPortButton.Text;
TheConnectPortButton.Text = "Busy, Please Wait"; /////// This never happens
ButtonBoss.ButtonHandler_ConnectPort();
TheConnectPortButton.Text = OldText; /////// Not sure if this happens
if (aUartSemaphoreThatTells.IfWeHaveConnectedToAPort == (int)aValueWhichIndicatesThat.YesWeHaveAGoodPortConnected)
{
TheConnectPortButton.Text = "Connected"; /////// This one does happen
}
}
aUartSemaphoreThatTells.IfWeHaveConnectedToAPort
例程也使用ButtonBoss
来确保他没有连接第二次以及其他按钮例程(例如,确保我们在Tx / Rx之前连接或者其他)。
我尝试在例程返回后更改代码...
if (aUartSemaphoreThatTells.IfWeHaveConnectedToAPort == (int)aValueWhichIndicatesThat.YesWeHaveAGoodPortConnected)
{
TheConnectPortButton.Text = "Connected";
}
else
{
TheConnectPortButton.Text = OldText;
}
......我仍然得到相同的结果。
我的猜测(而且就是这样)是线程在某种程度上涉及所有这些,并且串行端口例程通过一些我目前没有正确遵循的卷积来改变按钮文本更改例程。
问题:在连接内容占用系统之前,我需要做些什么才能让文本发生变化?
(如果那是发生的事情)
问题2:如果我不能做到这一点,我想我已经读过“灰化”按钮了,或者,我相信我看到某个地方我可以在用户的眼前实际制作一个按钮消失所以他不能再次点击它。欢迎使用示例代码的链接。
答案 0 :(得分:2)
问题是你正在从同一个事件处理程序执行所有操作,因此该按钮没有时间进行更新(重绘)。您可以调用Application.DoEvents();
方法,但这根本不是一个好主意,请阅读Use of Application.DoEvents()
我认为通常你会把一个耗时的任务推到一个单独的线程中,从中获取进度报告并更新你的GUI。有很多方法可以创建一个“工作者”线程并从中获得一些响应。例如,使用BackgroundWorker Class:
public partial class Form1 : Form
{
public Form1() { InitializeComponent(); }
private void button1_Click(object sender, EventArgs e)
{
BackgroundWorker w = new BackgroundWorker();
w.WorkerReportsProgress = true;
w.DoWork += new DoWorkEventHandler(w_DoWork);
w.ProgressChanged += new ProgressChangedEventHandler(w_ProgressChanged);
w.RunWorkerCompleted += new RunWorkerCompletedEventHandler(w_RunWorkerCompleted);
w.RunWorkerAsync();
button1.Text = "Started";
}
//may influence GUI, as this event handler is run on the GUI thread
void w_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Text = "Job is done";
}
//may influence GUI, as this event handler is run on the GUI thread
void w_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
button1.Text = e.ProgressPercentage.ToString();
}
//runs in the worker thread...should do the actual job
//may influence GUI through `ReportProgress`
//or through `Invoke` method
void w_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; i <= 10; i++)
{
Thread.Sleep(500);
worker.ReportProgress(10 * i);
}
}
}
或者您可以使用Task Class:
public partial class Form1 : Form
{
public Form1() { InitializeComponent(); }
private void button1_Click(object sender, EventArgs e)
{
new Task(DoTask).Start();
}
void DoTask()
{
for (int i = 1; i <= 10; i++)
{
Thread.Sleep(500);
//here you need to update GUI through `Invoke` method
//as the GUI may only be influenced from the the thread,
//where it's created
this.Invoke(new Action<int>((j) =>
{
button1.Text = j.ToString();
}), 10 * i);
}
}
}