一个多线程的问题

201ka 2003-08-22 10:36:48
如果一个线程 在执行的时候遇见一个语句

但这个语句或许要消耗大量时间

我想让这个语句如果10秒不能完成的话 就忽略这个语句而直接执行下一句

怎么做?

还有个问题:如何让一个线程重新启动

...全文
41 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
wolfpzp 2003-09-12
  • 打赏
  • 举报
回复
GZ
Surpass 2003-08-29
  • 打赏
  • 举报
回复
学习
alaisalaix 2003-08-29
  • 打赏
  • 举报
回复
(转载)
在.NET中编写的程序将被自动的分配一个线程.让我们来看看用C#编程语言创建线程并且继续学习线程的知识。我们都知道.NET的运行时环境的主线程由Main ()方法来启动应用程序,而且.NET的编译语言有自动的垃圾收集功能,这个垃圾收集发生在另外一个线程里面,所有的这些都是后台发生的,让我们无法感觉到发生了什么事情.在这里默认的是只有一个线程来完成所有的程序任务,但是正如我们在第一篇文章讨论过的一样,有可能我们根据需要自己添加更多的线程让程序更好的协调工作。比如说我们的例子中,一个有用户输入的同时需要绘制图形或者完成大量的运算的程序,我们必须得增加一个线程,让用户的输入能够得到及时的响应,因为输入对时间和响应的要求是紧迫的,而另外一个线程负责图形绘制或者大量的运算。

.NET 基础类库的System.Threading命名空间提供了大量的类和接口支持多线程。这个命名空间有很多的类,我们将在这里着重讨论Thread这个类。

System.Threading.Thread类是创建并控制线程,设置其优先级并获取其状态最为常用的类。他有很多的方法,在这里我们将就比较常用和重要的方法做一下介绍:

Thread.Start():启动线程的执行;

Thread.Suspend():挂起线程,或者如果线程已挂起,则不起作用;

Thread.Resume():继续已挂起的线程;

Thread.Interrupt():中止处于 Wait或者Sleep或者Join 线程状态的线程;

Thread.Join():阻塞调用线程,直到某个线程终止时为止

Thread.Sleep():将当前线程阻塞指定的毫秒数;

Thread.Abort():以开始终止此线程的过程。如果线程已经在终止,则不能通过Thread.Start()来启动线程。

通过调用Thread.Sleep,Thread.Suspend或者Thread.Join可以暂停/阻塞线程。调用Sleep()和Suspend()方法意味着线程将不再得到CPU时间。这两种暂停线程的方法是有区别的,Sleep()使得线程立即停止执行,但是在调用Suspend()方法之前,公共语言运行时必须到达一个安全点。一个线程不能对另外一个线程调用Sleep()方法,但是可以调用Suspend()方法使得另外一个线程暂停执行。对已经挂起的线程调用Thread.Resume()方法会使其继续执行。不管使用多少次Suspend()方法来阻塞一个线程,只需一次调用Resume()方法就可以使得线程继续执行。已经终止的和还没有开始执行的线程都不能使用挂起。Thread.Sleep(int x)使线程阻塞x毫秒。只有当该线程是被其他的线程通过调用Thread.Interrupt()或者Thread.Abort()方法,才能被唤醒。如果对处于阻塞状态的线程调用Thread.Interrupt()方法将使线程状态改变,但是会抛出ThreadInterupptedException异常,你可以捕获这个异常并且做出处理,也可以忽略这个异常而让运行时终止线程。在一定的等待时间之内,Thread.Interrupt()和Thread.Abort()都可以立即唤醒一个线程。

下面我们将说明如何从一个线程中止另外一个线程。在这种情况下,我们可以通过使用Thread.Abort()方法来永久销毁一个线程,而且将抛出ThreadAbortException异常。使终结的线程可以捕获到异常但是很难控制恢复,仅有的办法是调用Thread.ResetAbort()来取消刚才的调用,而且只有当这个异常是由于被调用线程引起的异常。因此,A线程可以正确的使用Thread.Abort()方法作用于B线程,但是B线程却不能调用Thread.ResetAbort()来取消Thread.Abort()操作。Thread.Abort()方法使得系统悄悄的销毁了线程而且不通知用户。一旦实施Thread.Abort()操作,该线程不能被重新启动。调用了这个方法并不是意味着线程立即销毁,因此为了确定线程是否被销毁,我们可以调用Thread.Join()来确定其销毁,Thread.Join()是一个阻塞调用,直到线程的确是终止了才返回。但是有可能一个线程调用Thread.Interrupt()方法来中止另外一个线程,而这个线程正在等待Thread.Join()调用的返回。

尽可能的不要用Suspend()方法来挂起阻塞线程,因为这样很容易造成死锁。假设你挂起了一个线程,而这个线程的资源是其他线程所需要的,会发生什么后果。因此,我们尽可能的给重要性不同的线程以不同的优先级,用Thread.Priority()方法来代替使用Thread.Suspend()方法。

Thread类有很多的属性,这些重要的属性是我们多线程编程必须得掌握的。

Thread.IsAlive属性:获取一个值,该值指示当前线程的执行状态。如果此线程已启动并且尚未正常终止或中止,则为 true;否则为 false。

Thread.Name 属性:获取或设置线程的名称
alaisalaix 2003-08-29
  • 打赏
  • 举报
回复
interrupt()方法可以正常(也就是使线程不会脱离其正常的状态)中断处于
waitsleepjoin状态的线程而引发中断异常ThreadInterruptedException,捕获中断异常,
在中断异常中catch{}块中,可以写入你的代码;一个线程如果处于wait、sleep、join状态
之一,另外一个线程调用interrupt()中断这个线程,这个线程将被激活,并处于Running状态
可以参考msdn文档。

操作 操作导致的线程状态
在公共语言运行库中创建线程 Unstarted
线程调用 Start Running
线程开始运行。 Running
线程调用 Sleep WaitSleepJoin
线程对其他对象调用 Wait。 WaitSleepJoin
线程对其他线程调用 Join。 WaitSleepJoin
另一个线程调用 Interrupt Running
另一个线程调用 Suspend SuspendRequested
线程响应 Suspend 请求。 Suspended
另一个线程调用 Resume Running
另一个线程调用 Abort AbortRequested
线程响应 Abort 请求。 Stopped
线程被终止。 Stopped
201ka 2003-08-29
  • 打赏
  • 举报
回复
那interrupt是起什么样的作用的呢
alaisalaix 2003-08-25
  • 打赏
  • 举报
回复
>>>第二个问题:如何让一个线程重新启动

线程如果是以Abort()终止后,这个线程将不能再通过Start()启动,因为其资源已被释放
可重新启动的线程有:
1。处于suspend状态的线程,通过resume()方法;
2。处于阻塞状态的线程(未获得Mutex的线程
或等待事件发生如WaitOne(),WaitAny(),WaitAll()的线程)
第一种等待其他线程释放Mutex,第二种等待事件(如AutoResetEvent、
ManualResetEvent)终止;
3。处于waitsleepjoin状态的线程(这种线程可正常中断,并发出中断异常)
这种线程状态是由于执行了sleep()或join()方法而产生
alaisalaix 2003-08-25
  • 打赏
  • 举报
回复
>>>第一个问题:我想让这个语句如果10秒不能完成的话 就忽略这个语句而直接执行下一句

这也不是不可能实现的,但要具体精确到10秒可能比较困难,因为每条语句的运行时间是
很难预测的,和机器配置,运行环境,系统负载等都可能有关系。我想了一种做法:
有一个线程来执行运行时间很长的语句,用一个辅助线程进行同步,该辅助线程用作 计时
并控制该线程的执行顺序

程序大致结构如下:
声明两个ManualResetEvent或AutoResetEvent变量:
ManualResetEvent mre1=new ManualResetEvent(false);//初始状态为非终止
ManualResetEvent mre2=new ManualResetEvent(true);//初始状态为终止
两个线程:
Thread t1=new Thread(T1);
Thread t2=new Thread(T2);
线程如下:
void T1()
{
...
...
try
{
...
mre1.Set();
LongRunTime();//运行时间很长的语句
mre2.Reset();
next1();
next2();
...
}
catch(ThreadInterruptedException)
{
next1();
next2()
...
}
catch(ThreadAbortException)
{
next1();
next2();
...
}
catch(ThreadStateException)
{
next1();
next2();
...
}
}
辅助线程:
void T2()
{
...
...
mre1.WaitOne();
Thread.Sleep(10000);
mre2.WaitOne();
t1.Interrupt();//或者t1.Abort()
...
}

201ka 2003-08-23
  • 打赏
  • 举报
回复
顶一下
201ka 2003-08-23
  • 打赏
  • 举报
回复
再顶一下
alaisalaix 2003-08-23
  • 打赏
  • 举报
回复
msdn讲得很细,而且有例子,直接搜索“线程”
huguojunsy 2003-08-23
  • 打赏
  • 举报
回复
不好意思,上面的有些错误.下面的试过,应该没问题了.
bigTask()里面的Thread.Sleep(15000)中的15000为假定的运行时间,你可以改为小于10000试试看.
using System;
using System.Threading;
class Test
{
public AutoResetEvent autoRE = new AutoResetEvent(false);
public Thread counterThread;
public Thread bigTaskThread;
public static void Main()
{

Test test=new Test();
test.counterThread=new Thread(new ThreadStart(test.Counter));
test.bigTaskThread=new Thread(new ThreadStart(test.BigTask));
test.counterThread.Start();
test.bigTaskThread.Start();
test.autoRE.WaitOne();
System.Console.ReadLine();
}
public void Counter()
{
for(int i=0;i<10;i++)
{
Thread.Sleep(1000);
System.Console.WriteLine(".............第{0}秒................",i);
}
if(bigTaskThread.IsAlive)
bigTaskThread.Abort();
autoRE.Set();
System.Console.WriteLine("................bigTaskThread 运行超过10秒,已经跳过!!!....................");
}
public void BigTask()
{
Thread.Sleep(15000);//你可以把这条语句替代为你所说的那条可能很费时间的代码(段)
autoRE.Set();
if(counterThread.IsAlive)
counterThread.Abort();
System.Console.WriteLine("................bigTaskThread 运行完毕!!!....................");
}
}
alaisalaix 2003-08-23
  • 打赏
  • 举报
回复
你的这个语句是什么语句?
如果是死循环,可以加一个计数器,由计数器定时间
当计数器到达最大值(max,由自己定义)时,退出循环,执行下一句


c#中如果一个线程被abort,这个线程好像就不能再start了
你可以用suspend()和resume()来挂起恢复线程,
或用中断interrupt结合中断异常ThreadInterruptedException来控制线程
或释放旧线程,重开新的线程
huguojunsy 2003-08-23
  • 打赏
  • 举报
回复
using System;
using System.Threading;
class Test
{
public AutoResetEvent autoRE = new AutoResetEvent(false);
public static void Main()
{
Thread counterThread;
Thread bigTaskThread;
Test test=new Test();
counterThread=new Thread(new ThreadStart(test.Counter));
bigTaskThread=new Thread(new ThreadStart(test.BigTask));
counterThread.Start();
bigTaskThread.Start();
test.autoRE.WaitOne();
System.Console.WriteLine("................bigTaskThread 运行超过10秒,已经跳过!!!....................");
System.Console.ReadLine();
}
public void Counter()
{
for(int i=0;i<10;i++)
{
Thread.Sleep(1000);
System.Console.WriteLine(".............第{0}秒................",i);
}
autoRE.Set();
}
public void BigTask()
{
Thread.Sleep(15000);//你可以把这条语句替代为你所说的那条可能很费时间的代码(段)
}
}

110,536

社区成员

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

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

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