我在加载事件中创建了一个线程,如下所示:
Thread checkAlert = null;
bool isStop = false;
private void frmMain_Load(object sender, EventArgs e)
{
checkAlert = new Thread(CheckAlert);
checkAlert.Start();
}
void CheckAlert()
{
while (!isStop)
{
Thread.Sleep(60000);
//do work here
}
}
有没有办法在休眠期间恢复checkAlert线程?(Thread.Sleep(60000);
)
我尝试使用Thread.Interrupt()
但它会流ThreadInterruptedException
,我该如何处理此异常?或者有没有办法恢复线程?
编辑:
我需要在“睡眠”结束之前唤醒线程,因为当用户想要退出程序时,程序必须等待一段时间才能真正退出(checkAlert仍在运行)有没有办法改善这种情况?
答案 0 :(得分:3)
如果您希望线程在程序退出时自动退出,只需将其设为后台线程即可。
checkAlert = new Thread(CheckAlert);
checkAlert.IsBackground = true;
checkAlert.Start();
答案 1 :(得分:2)
根据您的评论看起来是什么样的,您需要重新设计CheckAlert
的工作方式,以便它根本不使用Sleep。您应该做的是改为使用Timer
。
System.Timers.Timer timer = null;
public FrmMain()
{
InitializeComponent();
timer = new System.Timers.Timer(60000);
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
//If you want OnTimedEvent to happen on the UI thread instead of a ThreadPool thread, uncomment the following line.
//timer.SynchronizingObject = this;
if(this.components == null)
this.components = new System.ComponentModel.Container();
//This makes it so when the form is disposed the timer will be disposed with it.
this.componets.Add(timer);
}
private void frmMain_Load(object sender, EventArgs e)
{
timer.Start();
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
//It is good practice not to do complicated logic in a event handler
// if we move the logic to its own method it is much easier to test (you are writing unit tests, right? ;) )
CheckAlert();
}
void CheckAlert()
{
//do work here
}
private void frmMain_Close(object sender, EventArgs e)
{
timer.Stop();
}
答案 2 :(得分:1)
在我看来,你正在尝试创建一个处理两种类型事件的线程:做某事并停止运行。
您可能希望使用线程事件(而不是混淆高级UI {{1} } objects)来控制你的线程。
isStop
在代码中调用Event
将触发线程中的“do work”分支,AutoResetEvent stop = new AutoResetEvent(false);
AutoResetEvent check = new AutoResetEvent(false);
private void CheckAlert() {
WaitHandle[] handles = new WaitHandle[] { stop, check };
for (;;) {
switch (AutoResetEvent.WaitAny(handles)) {
case 0:
return;
case 1:
// do work
break;
}
}
}
将导致线程正常终止。
一旦你的代码调用check.Set()
来终止线程,它就可以调用线程的stop.Set()
方法来等待线程终止。
修改强> 的
我误解了这个问题。我将保留上面的代码,以防任何人发现它有用。 如果你想做的就是拥有一个每分钟执行一次任务并按需停止的线程,你可以使用以下代码:
stop.Set()
答案 3 :(得分:1)
您可以在此处查看有关如何唤醒睡眠线程的说明:
https://msdn.microsoft.com/en-us/library/tttdef8x%28v=vs.100%29.aspx
这是一个完整的例子(正如你所看到的,Thread.Interrupt是一个很好的选择......但你必须抓住它才能继续正常的线程执行):
public class HVCSensor : HVCDevice, IDisposable
{
private Thread myThread;
private const int execute_timeout = ((10 + 10 + 6 + 3 + 15 + 15 + 1 + 1 + 15 + 10) * 1000);
private bool disposed = false;
private bool paused = false;
public delegate void HVCResultsHandler(HVC_RESULT res);
public event HVCResultsHandler HVCResultsArrived;
private void OnHVCResultsArrived(HVC_RESULT res)
{
if (HVCResultsArrived != null) {
HVCResultsArrived(res);
}
}
public HVCSensor() {
myThread = new Thread(new ThreadStart(this.execute));
}
private void execute(){
while (!disposed) {
if (!paused && this.IsConnected)
{
HVC_RESULT outRes;
byte status;
try
{
this.ExecuteEx(execute_timeout, activeDetections, imageAcquire, out outRes, out status);
OnHVCResultsArrived(outRes);
}
catch (Exception ex) {
}
}
else {
try
{
Thread.Sleep(1000);
}
catch (ThreadInterruptedException e)
{
}
}
}
}
public HVC_EXECUTION_IMAGE imageAcquire
{
get;
set;
}
public HVC_EXECUTION_FLAG activeDetections
{
get;
set;
}
public void startDetection() {
if(myThread.ThreadState==ThreadState.Unstarted)
myThread.Start();
}
public void pauseDetection() {
paused = true;
}
public void resumeDetection() {
paused = false;
if (myThread.ThreadState == ThreadState.WaitSleepJoin)
myThread.Interrupt();
}
// Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
disposed = true;
myThread.Interrupt();
}
}