各位大侠, 兄弟刚学线程, 觉得好迷茫, 入不了门, 还望指点迷津。
我写了一个例子, 想实现的效果是,点击按钮后, label1从10000依次显示到1,同时进度条progressBar1显示进度, 可实际准果是, 只进度条显示进度, 而label1没反应, 代码如下:
private void button1_Click(object sender, EventArgs e)
{
//Thread T2 = new Thread(new ThreadStart(ThreadMethod));
Thread T2 = new Thread(new ThreadStart(ExecuteMethod));
T2.Start();
}
delegate void add();//委托
private void ExecuteMethod()
{
this.BeginInvoke(new add(ThreadMethod));
} private void ThreadMethod()
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 10000;
progressBar1.Step = 1;
label1.Text = "10000";
for (int i = 1; i < 10000; i++)
{
label1.Text = System.Convert.ToString(System.Convert.ToInt32(label1.Text.Trim()) - 1);
progressBar1.PerformStep();
}
progressBar1.Value = 0;
}但如果我采用不安全的线程调用,即去掉
delegate void add();//委托
private void ExecuteMethod()
{
this.BeginInvoke(new add(ThreadMethod));
}
这三句, 直接在线程中, 调用ThreadMethod就可正常达到要求。当然, 得加上:
CheckForIllegalCrossThreadCalls = false;
但这种方式并不好, 我不想采用, 哪位大侠能告诉我, 上面怎么修改, 能达到我让label1和进度条同时变化的目的。 谢谢
我写了一个例子, 想实现的效果是,点击按钮后, label1从10000依次显示到1,同时进度条progressBar1显示进度, 可实际准果是, 只进度条显示进度, 而label1没反应, 代码如下:
private void button1_Click(object sender, EventArgs e)
{
//Thread T2 = new Thread(new ThreadStart(ThreadMethod));
Thread T2 = new Thread(new ThreadStart(ExecuteMethod));
T2.Start();
}
delegate void add();//委托
private void ExecuteMethod()
{
this.BeginInvoke(new add(ThreadMethod));
} private void ThreadMethod()
{
progressBar1.Minimum = 0;
progressBar1.Maximum = 10000;
progressBar1.Step = 1;
label1.Text = "10000";
for (int i = 1; i < 10000; i++)
{
label1.Text = System.Convert.ToString(System.Convert.ToInt32(label1.Text.Trim()) - 1);
progressBar1.PerformStep();
}
progressBar1.Value = 0;
}但如果我采用不安全的线程调用,即去掉
delegate void add();//委托
private void ExecuteMethod()
{
this.BeginInvoke(new add(ThreadMethod));
}
这三句, 直接在线程中, 调用ThreadMethod就可正常达到要求。当然, 得加上:
CheckForIllegalCrossThreadCalls = false;
但这种方式并不好, 我不想采用, 哪位大侠能告诉我, 上面怎么修改, 能达到我让label1和进度条同时变化的目的。 谢谢
来不及刷新lable上的文字,在这句后面加一个Application.DoEvents();或者你开两个线程,一个显示lable,一个控制processbar
http://topic.csdn.net/u/20080306/17/0e289637-2d1e-4800-b017-472b83ed647f.html
所以for循环——真正能够处理数据的程序——还是要在子线程中执行,而修改label、progressbar的代码才需要在主线中执行。而你没有把它们分解开,所以一会儿在子线程(先new了一个线程),一会儿在主线程(线程中由用begininvoke调用处理数据的程序。需要把你的ThreadMethod方法中的代码拆开,只有个别代码才在主线程执行,而for循环还是在子线程中执行。
给你一些我的代码:
//由于PictureBox1、Button_InsertSatelliteMapImage、ProgressBar1等均被涉及于线程,
//所以需要进行线程安全设置。
delegate void PictureBoxRefreshDelegate(); // 线程刷新picturebox1
private void PictureBoxRefresh() // 线程刷新picturebox1
{
if (PictureBox1.InvokeRequired)
{
PictureBoxRefreshDelegate d = new PictureBoxRefreshDelegate(PictureBoxRefresh);
this.Invoke(d);
}
else
{
PictureBox1.Refresh();
}
}
delegate void LabelTextChangedDelegate(string label_text);
private void LabelTextChanged(string label_text) //在线程使用控件Label1
{
if (label1.InvokeRequired)
{
LabelTextChangedDelegate d = new LabelTextChangedDelegate(LabelTextChanged);
this.Invoke(d, new Object[] { label_text });
}
else
{
label1.Text = label_text;
}
}
string t;
for (int i = 1; i < 10000; i++)
{
// label1.Text = System.Convert.ToString(System.Convert.ToInt32(label1.Text.Trim()) - 1); t = System.Convert.ToString(System.Convert.ToInt32(label1.Text.Trim()) - 1);
LabelTextChanged(t);
//progressBar1.PerformStep(); //progressBar1的线程保护代码你就自己模仿一下吧。
}
delegate void ProgressBarValueChangedDelegate(int progress_percent);
private void ProgressValueChanged(int progress_percent)
{
if (ProgressBar1.InvokeRequired )
{
ProgressBarValueChangedDelegate d =new ProgressBarValueChangedDelegate(ProgressValueChanged);
this.Invoke(d, new Object[] { progress_percent });
}
else
{
ProgressBar1.Value = progress_percent;
}
}
代码再次修改为:
string t;
for (int i = 1; i < 10000; i++)
{
// label1.Text = System.Convert.ToString(System.Convert.ToInt32(label1.Text.Trim()) - 1); t = System.Convert.ToString(System.Convert.ToInt32(label1.Text.Trim()) - 1);
LabelTextChanged(t);
ProgressValueChanged(i);
// progressBar1.PerformStep();
}