如何唤醒睡眠线?

时间:2014-01-04 15:47:31

标签: c# multithreading

我在加载事件中创建了一个线程,如下所示:

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仍在运行)有没有办法改善这种情况?

4 个答案:

答案 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();


    }

}