初学C#,想问如何使用三个线程

skywolfY 2006-11-17 09:50:58
我想建立3个线程A、B、C
A用来作比较费时的操作,这个一直运行,不用等待
B用来处理一些数据,这个和C互斥
C用来画图,,这个和B互斥
可代码写好后,要么是B一直运行,要么是C一直运行,不让别的线程抢占,可有时又能正确运行。不知什么原因。哪位高手能指点下啊!!!1

调用顺序,先调A,再调B,再调C,三个线程都运行起来。
下边是三个线程的主要函数代码
//类ClassData
public class ClassData
{
//读取耗时数据
//线程A
private void ReadDataFromOut(ref Data TData)
{//获取数据
//过程略....
//此过程不作waitone

}
//线程B
public void TransData()
{//处理数据
try
{
while(true)
{

if(mutex1 == null)
mutex1 = new Mutex(false,"_rs001");//mutex1 = new Mutex(true);
mutex1.WaitOne();
//其它处理
for(int i=0;i<10000;i++)
{
//数据处理

}
mutex1.ReleaseMutex();


}
}
catch(Exception)
{
}
}
}
//其它窗体中用这个作为线程函数,
//线程C
private void runDisplay()
{//显示数据
try
{
Application.DoEvents();
while(true)
{
Application.DoEvents();
Thread.Sleep(50);
// if(ClassData.mutex1 == null)
// ClassData.mutex1 = new Mutex(true,"abcdef");
ClassData.mutex1.WaitOne();
//TransData数据画图由画图
dataDisPlay();

ClassData.mutex1.ReleaseMutex();
}
}
catch(Exception Ex)
{

}
}
...全文
588 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
liujia_0421 2007-01-10
  • 打赏
  • 举报
回复
To:是呀。不放中间就能正常运行。放中间就不行

放中间当然不行啊..

mx.WaitOne()时线程(比如说线程1)得到互斥权,执行循环操作..可能此时又有一个线程(比如说线程2)执行到这里mx.WaitOne(),由于线程1还在进行循环操作,占用互斥权..

线程2得不到互斥权,只能等待...阻塞在mx.WaitOne()这个地方..

线程1执行循环结束,执行mx.ReleaseMutex(),释放互斥权,仅当此时,线程2执行mx.WaitOne(),得到互斥权,进行循环操作..

所以总体效果就是一个线程结束了,另一个线程才开始执行,而不会出现几个线程交叉执行的情况..

不知道是否说清楚了...
skywolfY 2007-01-10
  • 打赏
  • 举报
回复
是呀。不放中间就能正常运行。放中间就不行
liujia_0421 2007-01-04
  • 打赏
  • 举报
回复
现在也忘了具体是什么情况了..

你的意思是说你将循环放在mutex.WaitOne()和mutex.ReleaseMutex()之间了吗?

即:
mx.WaitOne();
//循环处理
mx.ReleaseMutex();

是这样吗?
liujia_0421 2007-01-04
  • 打赏
  • 举报
回复
好长年代已经很久了..

我都由五三角变成两星了..
skywolfY 2007-01-04
  • 打赏
  • 举报
回复
好久没来了。我认为这个问题有点意思,先不结贴,再等下看有没有人给指点下。就这个程序,错在哪里?
kook_tian 2006-11-23
  • 打赏
  • 举报
回复
LOOK:
http://www.hnce.net/Content/slick.238.html
skywolfY 2006-11-23
  • 打赏
  • 举报
回复
看嘛看嘛,有人得出和我说的一样的结果了,不可能没人遇到过吧?谁能帮忙解释下呀?
我知道一定是用法错误,但不明白为什么错,错在哪。
liujia_0421 2006-11-20
  • 打赏
  • 举报
回复
TO:
我现在的问题,一般情况下,线程运作正常,但出错的时候也很多。不是B线程waitOne,就是C线程WaitOne,如果B线程ReleaseMutex,常出现C线程无法抢占的现象,或者CReleaseMutex,B无法抢占。

也就是说当BReleaseMutex后,可能又被B拿到互斥权了,恶性循环,造成可能有很长一段时间,C拿不到互斥权..是这个意思吧...

这个问题确实有点麻烦,这样吧,你在每个线程执行完后,都Sleep一段时间,保证两个线程运行所需要的时间大致差不多,这样看行不行,试下吧...

Good Luck...
skywolfY 2006-11-20
  • 打赏
  • 举报
回复
补允一点
B、C分为两个线程,是因为B中处理的数据有可能很复杂。C中则是一些操作UI的功能。不希望UI操作对B中的数据处理产生影响。
另A中,不与B进行互斥,是因为设计方法,能保证A处理数据时,B不会冲掉原数据。
skywolfY 2006-11-20
  • 打赏
  • 举报
回复
先谢各位帮忙。
我的程序中,
1、mutex1是同一个互斥体,只不过同正常对象来说,这个被在一个类中定义。
2、B、C要不断的运行才能达到程序要求。整个系统就是为了这三个线程存在,不存在浪费资源的问题,不作这三个线程运作,系统也不会做别的事情。
3、代码中的循环只是示意中间有可能存在耗时操作。
4、挂起操作是好办法,不过程序中有特别情况。
我现在的问题,一般情况下,线程运作正常,但出错的时候也很多。不是B线程waitOne,就是C线程WaitOne,如果B线程ReleaseMutex,常出现C线程无法抢占的现象,或者CReleaseMutex,B无法抢占。
liujia_0421 2006-11-20
  • 打赏
  • 举报
回复
刚做了一个小例子,效果同楼主描述的一样,这个问题到底出在哪里,一时半会还搞不清楚...

帮你关注一下....
skywolfY 2006-11-20
  • 打赏
  • 举报
回复
线程中有sleep,不会占用100%cpu,我现在不明白的是,什么情况能出现两个线程无法互斥,只由一个线程不断作。
magicsnake 2006-11-20
  • 打赏
  • 举报
回复
为什么要挂起,因为可能会出现没有数据需要处理或者绘制的情况,在这种情况下,程序产生空运转,循环会进行的非常快,这时候CPU的资源被该线程完全100%占用,互斥释放后,我们不知道到底会是那个线程会获取互斥权,空运转的线程执行频率快,可能会有更大的机会获取权限,所以需要一个额外的事件驱动来进行控制,对空运转的线程进行挂起,以免它抢占互斥资源,只有当重新获取数据后再激活数据处理线程;同理,UI线程也需要同样的控制,尽量阻止线程的空转.

虽然你的服务器只有三个线程工作,但是你的B,C的空转同样会影响到A线程的执行效率.

总的说来,让线程空转是最失败的设计方法,建议楼主重新设置这几个线程吧
skywolfY 2006-11-20
  • 打赏
  • 举报
回复
我不希望for在mutex1.ReleaseMutex();后边。
skywolfY 2006-11-20
  • 打赏
  • 举报
回复
这个方法试过了。我认为不是这个原因 
mutex1 = new Mutex(false,"_rs001");//mutex1 = new Mutex(true);
mutex1.WaitOne();
mutex1.ReleaseMutex();/////////////这里变化
//其它处理
for(int i=0;i<10000;i++)
{
//数据处理

}

这样写就对,可是for在ReleaseMutex后边了。


cangwu_lee 2006-11-17
  • 打赏
  • 举报
回复
路过

superxiaomm 2006-11-17
  • 打赏
  • 举报
回复
up
skywolfY 2006-11-17
  • 打赏
  • 举报
回复
//ClassData.mutex1 = new Mutex(true,"abcdef");复制错了。
应为
ClassData.mutex1 = new Mutex(true,"_rs001");
zhuangwei_ 2006-11-17
  • 打赏
  • 举报
回复
帮顶。。mark
magicsnake 2006-11-17
  • 打赏
  • 举报
回复
看了一下,B,C线程的互斥调用没有问题,不过还是建议mutex1作为一个static的变量,还是在构建类的时候直接初始化好一些,不需要在线程中判断生成:
public static Mutex mutex1 = new Mutex();

我觉得你将B,C作为两个守护线程调用,是不是真的适合??按照你的设计,B,C两个线程一经启动,就算是没有可用的数据进行处理,也将会不断的相互交替循环运行,这样会很浪费CPU资源.我觉得应该在B线程中设定除了互斥体外的等待机制,就是判断是否有数据需要处理,如果没有数据处理,那么B应该做挂起操作,C因为互斥体,同时也应该被挂起.直到A得到足够的数据,才发送信号给B,使B继续运行.
另外,这两个互斥都是整个线程函数的互斥,这样的话根本没有必要分成两个线程来调用,因为他们肯定会互相交替的申请资源(B->C->B->C->B)(变成线性执行而不是并行执行了),绝对不会出现(B->B->B->C)这样的执行情况,所以只需要将方法写在同一个线程内顺序执行就行了,因为分开也不会提高执行效率.

关于只运行B或者C的情况,你需要检查一下是否在线程函数内有些地方出现了异常错误,结果导致线程死掉了.正常情况下,BC两个线程会一直交替循环执行
加载更多回复(3)

111,125

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧