C# “可以”;AutoResetEven';s Waitone();在停止windows服务时制造障碍?
在我的windows服务中,我启动了5个独立工作的线程,它们不编写公共资源(因此没有互斥或死锁) 但是一个线程有一个C# “可以”;AutoResetEven';s Waitone();在停止windows服务时制造障碍?,c#,windows,multithreading,C#,Windows,Multithreading,在我的windows服务中,我启动了5个独立工作的线程,它们不编写公共资源(因此没有互斥或死锁) 但是一个线程有一个自动resetEvent\u waitTillusBinstered.WaitOne()调用。基本上,该线程负责在插入USB后立即启动USB文件传输,因此它会等待直到从负责监视USB插入/删除事件的线程接收到通知信号(通过设置\u waitTillusBinstered,即调用\u waitTillusBinstered.Set()) 问题:是否可能因为\u waitTillusB
自动resetEvent
\u waitTillusBinstered.WaitOne()
调用。基本上,该线程负责在插入USB后立即启动USB文件传输,因此它会等待直到从负责监视USB插入/删除事件的线程接收到通知信号(通过设置\u waitTillusBinstered
,即调用\u waitTillusBinstered.Set()
)
问题:是否可能因为\u waitTillusBinstered.WaitOne()
,我的windows服务不会停止
询问原因:我试图通过windows服务管理器工具停止windows服务(按“停止”),但它无法停止服务(出现错误1053)。我终于不得不重新启动我的电脑。它一次又一次地发生(4-5次)。我注释掉了所有启动调用的线程,然后我可以停止我的windows服务。我取消了所有启动调用的线程的注释,但现在我可以停止windows服务(不做任何更改)。我无法重现该条件,但我怀疑原因可能是
\u waitTillusBinstered.WaitOne()
。如果您的线程是前台线程,并且您没有使用EventWaitHandle.WaitOne(Int32),那么是:该线程是前台线程,它会阻止进程终止,直到线程终止,然后等待一个()阻止线程,防止其终止
发件人:
线程可以是背景线程,也可以是前景线程。
背景线程与前景线程相同,只是
后台线程不阻止进程终止。一劳永逸
属于进程的前台线程已终止,公共
语言运行库结束该过程。任何剩余的后台线程
已停止且未完成。默认情况下,以下线程
在前台执行(即,其IsBackground属性
返回false):
- 主线程(或主应用程序线程)
- 通过调用线程类构造函数创建的所有线程
var thread = new Thread(ThreadStart)
{
IsBackground = true
}
当服务终止时,进程将正确退出,尽管线程正在阻止WaitHandle.WaitOne()调用
第二种方法是使用某种状态(通过引用传递)通知线程它应该终止。以下示例使用CancellationToken
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);
}
}
由您定义停止状态的含义。但是您肯定应该使用WaitAny(),这样当用户停止服务时线程也可以完成。这不是绝对必要的,您也可以忽略USB插入,或者在服务未激活时不使用USB设备。在OnStop事件中是否有任何内容?@ThingyWhat Windows中的服务只不过是在特殊上下文(服务控制管理器)中启动的可执行文件。由于所讨论的服务是一个.NET可执行文件,我们获得了.NET运行时的好处和含义,包括托管线程,它们遵循我在回答中提到的规则(前台与后台)。在前台线程和后台线程的上下文中,区别在于一个(前台)将阻止进程终止,而另一个(后台)将不会。OK-默认值必须是后台,然后,(否则我的C#服务将遇到麻烦:)。文档中明确指出,主线程以及通过new thread()创建的线程都是前台线程,除非您显式地将IsBackground设置为true。如果您使用的是线程池,那么这些线程都将是后台线程。