一般在寫 windows form 程式時
如果不是大型開發
老闆只要求 東西能動 項目立刻好
我們可能就會把 邏輯寫在控件事件內 像是
button1_Click(object sender, EventArgs e)
如果控件事件內塞了迴圈 迴圈內的又希望能更新UI顯示的內容 如下寫法會失敗
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Control_Refresh_1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 11; i++)
{
Thread.Sleep(200);
textBox1.Text = i.ToString();
}
}
}
}
上面的例子 迴圈完全跑完才會顯示10 中間的數字完全沒出現
強制控制項使其工作區失效,並且立即重繪其本身和任何子控制項。
實際使用就是在對的地方加上
this.Refresh();
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Control_Refresh_1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 11; i++)
{
Thread.Sleep(200);
textBox1.Text = i.ToString();
this.Refresh();
}
}
}
}
https://www.ez2o.com/Blog/Post/csharp-Object-Refresh
https://www.cnblogs.com/aooyu/archive/2012/04/12/2444395.html
主要是刷新UI是主執行緒 你Thread.Sleep阻塞住主執行緒 所以不會更新
可以採用非同步方式 不阻塞主執行緒
button.Click += async (s, e) =>
{
for (int i = 0; i < 11; i++)
{
await Task.Delay(200);
text.Text = i.ToString();
}
};
可是把Thread.Sleep拿掉 看起來也不會更新
似乎 只有等迴圈跑完才更新一次
進入 button1_Click的還是主執行緒
主執行緒要跑完迴圈才會有空繼續往下做事情
我把我這邊寫法的迴圈展開給你看
await Task.Delay(200);//進來的執行緒休息去做其他事情(不一定是主執行緒)
text.Text = 0.ToString();
await Task.Delay(200);//進來的執行緒休息去做其他事情(不一定是主執行緒) 執行完這行畫面才會更新為0 因為主執行緒是有空的
text.Text = 1.ToString();
await Task.Delay(200);//進來的執行緒休息去做其他事情(不一定是主執行緒) 執行完這行畫面才會更新為1 因為主執行緒是有空的
text.Text = 2.ToString();
await Task.Delay(200);//進來的執行緒休息去做其他事情(不一定是主執行緒) 執行完這行畫面才會更新為2 因為主執行緒是有空的
text.Text = 3.ToString();
await Task.Delay(200);//進來的執行緒休息去做其他事情(不一定是主執行緒) 執行完這行畫面才會更新為3 因為主執行緒是有空的
謝謝 我研究看看
你可以把原button1_Click內容改寫成這樣
我不讓主執行緒跑計數器
新創建一個執行緒來跑
但是因為不在主執行緒內不能更新UI
所以要將更新UI的事情轉回去給主執行緒(this.Invoke)
var thread = new Thread(() =>
{
for (int i = 0; i < 11; i++)
{
Thread.Sleep(200);
this.Invoke(new MethodInvoker(() =>
{
text.Text = i.ToString();
}));
}
});
thread.Start();
感謝兩位大哥教導
以下也有說明C#的更新方法,挺有趣
https://blog.csdn.net/cxu123321/article/details/107318628
ps.我是在text.Text 更換後才寫thread.sleep();
想不到text.Text都沒更新完就Sleep了N秒
thread.sleep() 會讓整個視窗都無法移動和其他[運作]
謝謝回應
我終於結束 拖稿了
https://ithelp.ithome.com.tw/articles/10313001