Нэнси с Topshelf не работает, когда работает как служба? C#
Я создал собственный хостинг с Нэнси, а затем хочу, чтобы приложение запускалось как сервисы. Поэтому я использую верхнюю полку, чтобы построить его. Затем, когда я отлаживаю свою программу или запускаю.exe, программа работает хорошо. Но когда я устанавливаю.exe как службу и запускаю службу. Я не могу вызвать API, который я создаю с помощью nancy (в браузере только "ожидание localhost..", ошибка или ошибка не возвращаются). Это из-за рабочего каталога, многопоточности или чего-то еще? благодарю вас
Вот мой код: Program.cs
public class Program
{
[STAThread]
public static void Main()
{
var thread = new Thread(WorkerMethod);
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = false;
thread.Start();
}
public static void WorkerMethod(object state)
{
HostFactory.Run(x =>
{
x.Service<HostingAPI>(s =>
{
s.ConstructUsing(name => new HostingAPI());
s.WhenStarted(tc => tc.Start());
s.WhenStopped(tc => tc.Stop());
});
x.RunAsLocalSystem();
x.SetDescription("Hardware hosting API");
x.SetDisplayName("Hosting Services for Hardware");
x.SetServiceName("Hardware Services");
});
}
}
CDM_Module (модуль nancy)
public class CDM_Module : NancyModule
{
public CDM_Module()
{
try
{
Get["/CDM/Machine/Start"] = parameters =>
{
var ins = HostingAPI.Instance;
bool result = ins.InitCDM_Thread();
return Response.AsJson(result);
};
Get["/CDM/Machine/OpenGate"] = parameters =>
{
var ins = HostingAPI.Instance;
bool result = ins.StartProcess_Thread();
return Response.AsJson(result);
};
Get["/CDM/Machine/CloseGate"] = parameters =>
{
var ins = HostingAPI.Instance;
bool result = ins.StopProcess_Thread();
return Response.AsJson(result);
};
}
catch
{
}
}
}
HostingAPI.cs (функция запуска и остановки и одна функция, вызываемая для API)
public class HostingAPI
{
//global variable
private NancyHost mainHost;
public static HostingAPI Instance;
private string hostUrl;
//public static MainCDM Ins = new MainCDM();
public clsCSDDPMControl ObjDPMControl = new clsCSDDPMControl();
public ClsPrinterControl ObjPrinterControl = new ClsPrinterControl();
//webservice
HttpClient httpClient = new HttpClient();
public void Start()
{
//set hosturl dari document xml nantinya
//sementara default
//under construction
Config.ReadConfiguration();
//set awal entity
buildEntity();
AddEventCDM();
AddEventPrinter();
Instance = this;
if (hostUrl == null) hostUrl = "http://localhost:5030";
mainHost = new NancyHost(new Uri(hostUrl));
mainHost.Start();
//Console.WriteLine("Hardware Hosting API is running on " + hostUrl);
}
public void Stop()
{
mainHost.Stop();
//Console.WriteLine("Service stopped!");
}
public bool InitCDM_Thread()
{
var thread = new Thread(InitCDM);
thread.SetApartmentState(ApartmentState.STA);
thread.IsBackground = false;
thread.Start();
Dummy.m_autoreset.WaitOne();
return rtn;
}
private void AddEventCDM()
{
ObjDPMControl.EvtBoxFullReceived += new clsCSDDPMControl.EvtBoxFullReceivedEventHandler(ObjDPMControl_EvtBoxFullReceived);
ObjDPMControl.EvtDocDataReceived += new clsCSDDPMControl.EvtDocDataReceivedEventHandler(ObjDPMControl_EvtDocDataReceived);
ObjDPMControl.EvtDocumentCounterReceived += new clsCSDDPMControl.EvtDocumentCounterReceivedEventHandler(ObjDPMControl_EvtDocumentCounterReceived);
ObjDPMControl.EvtDPMShellMsgReceived += new clsCSDDPMControl.EvtDPMShellMsgReceivedEventHandler(ObjDPMControl_EvtDPMShellMsgReceived);
ObjDPMControl.EvtErrMsgReceived += new clsCSDDPMControl.EvtErrMsgReceivedEventHandler(ObjDPMControl_EvtErrMsgReceived);
ObjDPMControl.EvtEventsReceived += new clsCSDDPMControl.EvtEventsReceivedEventHandler(ObjDPMControl_EvtEventsReceived);
ObjDPMControl.EvtImageStoredReceived += new clsCSDDPMControl.EvtImageStoredReceivedEventHandler(ObjDPMControl_EvtImageStoredReceived);
ObjDPMControl.EvtImageStoredErrorReceived += new clsCSDDPMControl.EvtImageStoredErrorReceivedEventHandler(ObjDPMControl_EvtImageStoredErrorReceived);
ObjDPMControl.EvtStatusReceived += new clsCSDDPMControl.EvtStatusReceivedEventHandler(ObjDPMControl_EvtStatusReceived);
ObjDPMControl.AxEvtBackTraceFileReady += new clsCSDDPMControl.AxEvtBackTraceFileReadyEventHandler(ObjDPMControl_AxEvtBackTraceFileReady);
ObjDPMControl.AxEvtComPortError += new clsCSDDPMControl.AxEvtComPortErrorEventHandler(ObjDPMControl_AxEvtComPortError);
ObjDPMControl.AxEvtExtraImageError += new clsCSDDPMControl.AxEvtExtraImageErrorEventHandler(ObjDPMControl_AxEvtExtraImageError);
ObjDPMControl.AxEvtFrontDitherReady += new clsCSDDPMControl.AxEvtFrontDitherReadyEventHandler(ObjDPMControl_AxEvtFrontDitherReady);
ObjDPMControl.AxEvtOutOfOrder += new clsCSDDPMControl.AxEvtOutOfOrderEventHandler(ObjDPMControl_AxEvtOutOfOrder);
ObjDPMControl.AxEvtRearDitherReady += new clsCSDDPMControl.AxEvtRearDitherReadyEventHandler(ObjDPMControl_AxEvtRearDitherReady);
DeviceReplyCode = Convert.ToInt32(ObjDPMControl.InitDevices(Config.DpmIniFile));
}
private void InitCDM()
{
DeviceReplyCode = Convert.ToInt32(ObjDPMControl.InitDevices(Config.DpmIniFile));
if (DeviceReplyCode == ObjDPMControl.CSDeviceSuccessCode)
{
if (ObjDPMControl.StartDPMEngine() == true)
{
if (ObjDPMControl.DPMSetTimeouts() == true)
{
rtn = true;
}
else
{
rtn = false;
}
}
else
{
rtn = false;
}
}
else
{
rtn = false;
}
Dummy.m_autoreset.Set();
}
}
РЕДАКТИРОВАТЬ
Уже пытаются поймать исключение, но никто не пойман. Я пытаюсь комментировать Dummy.m_autoreset.WaitOne() и Dummy.m_autoreset.Set(). Теперь API работает, но функция внутри InitCDM() не выполняется? В этой функции я вызываю некоторую библиотеку для машины, чем машина возвращает обратную связь напрямую или через обработчик событий. Я думаю, что обработчик событий, который я создаю с помощью AddEventCDM(), не доступен библиотекой, потому что поток больше не доступен? Любой совет?
1 ответ
Попробуйте запустить NancyHost в новом потоке в методе Start(). В моем случае метод Start() не вернулся, что сделало невозможным запуск в качестве службы Windows.