这是我的C#线程一章的作业,先同时运行第一、二号线程,都完了之后,才运行第三号线程。但是写到两个线程都完了之后,我就不知道怎样写返回主线程了的代码了。
这种窗口程序又和控制台程序不一样,控制台程序返回到main()方法就可以了,但这种我就不知道支线程完了之后,返回到主线程是返回到哪里去了。开始还以为返回到“frmThreadTest”(即主form)中,不对;返回到按钮点击事件中,也不对。真不知如何是好。
而且两个支线程有可能不是同时结束的,所以本来下面三句代码可以在回到主线程之后才写,结果因为不知道怎么回到主线程,要分别写在两个方法下面,导致代码冗余。
dt2 = DateTime.Now;
lblEnd.Text = dt2.ToLongTimeString() + "." + dt2.Millisecond;
lblUsed.Text = (dt2 - dt1).ToString();
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;namespace ThreadTest
{
public partial class frmThreadTest : Form
{
Thread t1,t2;
Random r;
DateTime dt2;
DateTime dt1; public frmThreadTest()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
int seed = DateTime.Now.Millisecond;
r = new Random(seed);
} private void btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
} public void RunLabel(Label lbl)
{
lbl.Text = r.Next(0, 10).ToString();
} public void RunLabel1()
{
for (int i = 0; i < 100; i++)
{
RunLabel(lbl1);
Thread.Sleep(100);
}
dt2 = DateTime.Now;
lblEnd.Text = dt2.ToLongTimeString() + "." + dt2.Millisecond;
lblUsed.Text = (dt2 - dt1).ToString();
t1.Join();
} public void RunLabel2()
{
for (int i = 0; i < 100; i++)
{
RunLabel(lbl2);
Thread.Sleep(100);
}
dt2 = DateTime.Now;
lblEnd.Text = dt2.ToLongTimeString() + "." + dt2.Millisecond;
lblUsed.Text = (dt2 - dt1).ToString();
t2.Join();
}
private void btnStart_Click(object sender, EventArgs e)
{
dt1 = DateTime.Now;
lblStart.Text = dt1.ToLongTimeString() + "." + dt1.Millisecond;
lblEnd.Text = "";
lblUsed.Text = "共耗时:";
t1 = new Thread(new ThreadStart(RunLabel1));
t2 = new Thread(new ThreadStart(RunLabel2));
t1.Start();
t2.Start();
} private void btnStop_Click(object sender, EventArgs e)
{
t1.Abort();
t2.Abort();
} private void frmThreadTest_Load(object sender, EventArgs e)
{}
}
}
这种窗口程序又和控制台程序不一样,控制台程序返回到main()方法就可以了,但这种我就不知道支线程完了之后,返回到主线程是返回到哪里去了。开始还以为返回到“frmThreadTest”(即主form)中,不对;返回到按钮点击事件中,也不对。真不知如何是好。
而且两个支线程有可能不是同时结束的,所以本来下面三句代码可以在回到主线程之后才写,结果因为不知道怎么回到主线程,要分别写在两个方法下面,导致代码冗余。
dt2 = DateTime.Now;
lblEnd.Text = dt2.ToLongTimeString() + "." + dt2.Millisecond;
lblUsed.Text = (dt2 - dt1).ToString();
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;namespace ThreadTest
{
public partial class frmThreadTest : Form
{
Thread t1,t2;
Random r;
DateTime dt2;
DateTime dt1; public frmThreadTest()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;
int seed = DateTime.Now.Millisecond;
r = new Random(seed);
} private void btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
} public void RunLabel(Label lbl)
{
lbl.Text = r.Next(0, 10).ToString();
} public void RunLabel1()
{
for (int i = 0; i < 100; i++)
{
RunLabel(lbl1);
Thread.Sleep(100);
}
dt2 = DateTime.Now;
lblEnd.Text = dt2.ToLongTimeString() + "." + dt2.Millisecond;
lblUsed.Text = (dt2 - dt1).ToString();
t1.Join();
} public void RunLabel2()
{
for (int i = 0; i < 100; i++)
{
RunLabel(lbl2);
Thread.Sleep(100);
}
dt2 = DateTime.Now;
lblEnd.Text = dt2.ToLongTimeString() + "." + dt2.Millisecond;
lblUsed.Text = (dt2 - dt1).ToString();
t2.Join();
}
private void btnStart_Click(object sender, EventArgs e)
{
dt1 = DateTime.Now;
lblStart.Text = dt1.ToLongTimeString() + "." + dt1.Millisecond;
lblEnd.Text = "";
lblUsed.Text = "共耗时:";
t1 = new Thread(new ThreadStart(RunLabel1));
t2 = new Thread(new ThreadStart(RunLabel2));
t1.Start();
t2.Start();
} private void btnStop_Click(object sender, EventArgs e)
{
t1.Abort();
t2.Abort();
} private void frmThreadTest_Load(object sender, EventArgs e)
{}
}
}
解决方案 »
- 如何获得一组不相同的随机数
- C#如何播放GSM6.10音频流
- serialport组件如何操作集成在笔记本中的wifi网卡
- 序列化与反序列化的问题,请大神指教
- 弱弱的问:vs 2010和 vs2008两者开发的程序在网络编程效率上有哪些区别?请举例
- 集合的若干问题
- DataGrid得问题,帮帮忙啊,真不知道,怎么回事 啊
- 程序就剩最后一步了,写入文件老是出错,郁闷
- 请问Delegate类而不是关键字delegate的使用方法!
- ListView & ImageList 删图问题
- Vs2008资源文件
- 怎么吧字符串转化为类似%u591A%u591A%u5173%u7167%u591A%u591A%u5173%u7167类型
那么可不可以一运行支线程,就让主线程的代码先停下,然后支线程的代码都运行完了,再运行主线程的代码呢?
而且,我实在想不到在窗口程序环境(相对控制台程序)下,主线程是怎样接收(接手)支线程的?是通过一个方法还是一个类?
我在按钮事件和form启动事件里面写都不行。
{
dt1 = DateTime.Now;
lblStart.Text = dt1.ToLongTimeString() + "." + dt1.Millisecond;
lblEnd.Text = "";
lblUsed.Text = "共耗时:";
t1 = new Thread(new ThreadStart(RunLabel1));
t2 = new Thread(new ThreadStart(RunLabel2));
t1.Start();
t2.Start(); while(t1.IsAlive || t2.IsAlive);
//可以加这里
}
join方法也用了,信号变量也设了。问题是支线程一运行完,不论是Alive或join还是abort,都好像不知道主线程在哪里,总之就停在线程调用的方法的末尾,不动了。
根本去不到信号变量的判断语句的位置(我是放在btnStart事件那里,也放过在form_load事件里,都不行),所以也运行不下去。
{
sleep(300);
if (!th1.Alive)
{
th2.stat();
return;
}
}
比如 int nowtype= 0;然后1,2,线程运行完后
nowtype ++;在主线程里
thread1.Start();
thread2.Start();while(nowtype<2)
{}
thread3.Start();建议你把这几个start单独放到一个线程里.然后在btn点进行加载
但是,15楼和16楼的“在主线程”里的代码,到底是写在什么地方合适呢?
我曾经在按钮事件btnStart_Click和窗体导入事件frmThreadTest_Load里写上这些代码,但支线程就是去到线程末尾的时候停下了。
所以请问16楼nealbox,“主线程”到底是在哪里呢?
public Form1 () {
} private btnStart_Click(object sender, EventArgs e) {
Thread t1 = new Thread(new ThreadStarter(Thread1_Proc));
Thread t2 = new Thread(new ThreadStarter(Thread2_Proc));
t1.Start();
t2.Start();
} private void OnThreadFinish(int threadID) {
//...... run in ui thread
Label1.Text += threadID.ToString()+" finished!";
} private delegate void DelegateOnThreadFinish(int); private void Thread1_Proc() {
//... do work
this.Invoke(new DelegateOnThreadFinish(OnThreadFinish), new object[]{1}); // call OnThreadFinished
}
private void Thread2_Proc() {
// ... do work
this.Invoke(new DelegateOnThreadFinish(OnThreadFinish), new object[]{2}); }
}
新建一个类
class NewThread()
{
public void main(){
thread1=new Thread(new ThreadStart(first));
thread2=new Thread(new ThreadStart(second));
thread3=new Thread(new ThreadStart(third));
thread newt = Thread(new ThreadStart(beginthread));
newt.Start();
}
private void beginthread()
{
thread1.Start();
thread2.Start(); while(nowtype <2)
{ }
thread3.Start();
}
}在first和second 里把全局变量nowtype ++
把主线程和保持运行等待的线程分开
不用写的再全了吧?
确实可以先运行完了一二线程,然后再运行第三件工作了,但我发现TA用的是又开一个线程,然后把停止了的一二线程归并到这个新线程里,所以其实一二线程结束之后,并没有回到主线程,而只是去到这个支线程而已。于是我把TA的代码稍微改了一下,不开一个新线程,而直接建一个方法,然后归并一二线程、然后开展之后的任务等等,都在这个方法里面完成就是了。就是把下面两行代码:
Thread TestT = new Thread(new ThreadStart(Test));
Test.Start();
直接改成Test();
直接运行就行了。但所有控件改变了值之后,下一句都要加上.Update();否则控件改变不能产生作用。
非常感谢amylee200808,因为是TA给了我思路。
做到这里,我又突然想起,其实我在学校做这个作业的时候,已经问过我的老师,但老师有事赶时间,只说了一句:你建一个方法来收集这两个线程嘛。但当时我脑子不知道怎的堵住了,总是想不通:支线程完了之后,怎么知道要自己跑去那个方法里面去呢?
只是这个功课花费的时间太多了,其他同学的代码,我就没有一个一个试了。
谢谢各位同学。
原来界面上的一个用于测试停止线程的按钮,居然不能产生作用了。即下面几行代码。
private void btnExit_Click(object sender, EventArgs e)
{
Application.Exit();
}
然后用回amylee200808的建立线程的方法,按钮又能用了。
看来真是欲罢不能,可能要试试其他高手的代码了。