首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >"AutoResetEven's Waitone()“能否在停止windows服务方面设置障碍?

"AutoResetEven's Waitone()“能否在停止windows服务方面设置障碍?
EN

Stack Overflow用户
提问于 2017-04-05 13:30:14
回答 1查看 208关注 0票数 0

在我的windows服务中,我启动了5个独立工作的线程,这些线程不编写公共资源(因此没有互斥或死锁)。

但是有一个线程有一个AutoResetEvent _waitTillUSBInsterted.WaitOne()调用。基本上,该线程负责在插入USB后立即启动USB文件传输,因此它等待直到从负责监视USB插入/删除事件的线程接收到通知信号(通过设置_waitTillUSBInsterted即通过调用_waitTillUSBInsterted.Set())。

问题:会不会因为_waitTillUSBInsterted.WaitOne()而停止我的windows服务?

询问原因:I试图通过windows服务管理器工具(通过按下" stop ")停止windows服务,但它无法停止该服务(获得了错误1053)。我终于不得不重新启动我的电脑了。一次又一次地发生(4-5次)。我注释掉了所有线程--启动调用,然后是--我能够停止我的windows服务;,我取消了所有线程的注释--逐个启动调用,但现在我能够停止windows服务(不做任何更改)。我无法复制这种情况,但我怀疑_waitTillUSBInsterted.WaitOne()可能是原因。

EN

回答 1

Stack Overflow用户

发布于 2017-04-05 13:56:10

如果您的线程是前台线程,并且不使用EventWaitHandle.WaitOne(Int32),那么是的:线程是一个前台线程,它阻止进程终止,直到线程终止,WaitOne()阻止线程终止,从而阻止它终止。

来自System.Threading.Thread.IsBackground

线程要么是后台线程,要么是前台线程。后台线程与前台线程相同,但后台线程不会阻止进程终止。一旦进程的所有前台线程都结束了,公共语言运行库就会结束该进程。任何剩余的后台线程都会停止,并且不完成。默认情况下,以下线程在前台执行(即它们的IsBackground属性返回false):

  • 主线程(或主应用程序线程)。
  • 调用线程类构造函数创建的所有线程。

任何通过使用线程构造函数创建的线程,除非通过使用IsBackground属性进行专门配置,否则都将是前台线程,并将阻止进程终止直到进程终止。

来自System.Threading.WaitHandle.WaitOne()

阻塞当前线程,直到当前WaitHandle接收到信号为止。

有几种方法可以缓解这个问题。首先:如果可以让线程过早终止,那么就像这样构造线程:

代码语言:javascript
复制
var thread = new Thread(ThreadStart)
{
    IsBackground = true
}

当服务终止时,尽管线程阻塞了WaitHandle.WaitOne()调用,进程仍将正确退出。

第二种方法是使用某种类型的状态,通过引用传递,通知线程它应该终止。下面的示例使用CancellationToken。

代码语言:javascript
复制
using System.ServiceProcess;
using System.Threading;

public class ServiceState
{
    public ServiceState(CancellationToken cancellationToken, WaitHandle waitHandle)
    {
        this.CancellationToken = cancellationToken;
        this.WaitHandle = waitHandle;
    }

    public CancellationToken CancellationToken { get; }

    public WaitHandle WaitHandle { get; }
}

public class MyService : ServiceBase
{
    private readonly Thread serviceThread;
    private readonly CancellationTokenSource cancellationTokenSource;
    private readonly WaitHandle waitHandle;

    public Service()
    {
        serviceThread = new Thread(ThreadProc);
        cancellationTokenSource = new CancellationTokenSource();
        waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
    }

    protected override void OnStart(string[] args)
    {
        var state = new ServiceState(cancellationTokenSource.Token, waitHandle);
        serviceThread.Start(state);
    }

    protected override void OnStop()
    {
        cancellationTokenSource.Cancel();
        waitHandle.Set();
    }

    private static void ThreadProc(object state)
    {
        var serviceState = (ServiceState)state;

        do
        {
            serviceState.WaitHandle.WaitOne();
            if (serviceState.CancellationToken.IsCancellationRequested)
            {
                return; // This will terminate the thread.
            }

            // Thread logic goes here.
        } while (true);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43232701

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档