1 回答

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超6個(gè)贊
好的,現(xiàn)在清楚多了。好吧,理想情況下,您應(yīng)該從一些有關(guān) Windows 服務(wù)的構(gòu)成的教程開始 - 我打賭這可能已經(jīng)為您解決了問題。但無論如何我們還是要嘗試一下。
一些理論
Windows 服務(wù)有兩個(gè)方面:它執(zhí)行一些有用的任務(wù)并與SCM 設(shè)施進(jìn)行通信。當(dāng)您使用命令或通過控制面板操作服務(wù)時(shí)sc
,您可以使用該軟件代表您與 SCM 進(jìn)行對(duì)話,而 SCM 則與該服務(wù)進(jìn)行對(duì)話。
SCM 和服務(wù)使用的確切協(xié)議是低級(jí)且復(fù)雜的,您使用的 Go 包的目的是向您隱藏這種復(fù)雜性,并為這些東西提供一個(gè)合理的以 Go 為中心的接口。
正如您可能從自己的示例中了解到的那樣,Execute
您創(chuàng)建的類型的方法在很大程度上與與 SCM 的通信有關(guān):它運(yùn)行一個(gè)無限for
循環(huán),在每次迭代時(shí)都會(huì)休眠從r
通道讀取數(shù)據(jù),并且該通道將 SCM 命令傳送到您的服務(wù)。
所以你基本上擁有了所謂的“SCM 命令處理循環(huán)”。
現(xiàn)在回想一下上面的兩個(gè)方面。您已經(jīng)擁有其中之一:您的服務(wù)與 SCM 交互,因此您需要另一個(gè) — 實(shí)際執(zhí)行有用任務(wù)的代碼。
事實(shí)上,它已經(jīng)部分存在:您獲取的示例代碼創(chuàng)建了一個(gè)時(shí)間行情指示器,它提供了一個(gè)通道,當(dāng)另一個(gè)時(shí)間行情通過時(shí),它在該通道上傳遞值。for
該方法中的循環(huán)也Execute
從該通道讀取數(shù)據(jù),每次發(fā)出另一個(gè)刻度信號(hào)時(shí)都會(huì)“工作”。
好吧,這對(duì)于一個(gè)玩具示例來說很好,但對(duì)于真正的作品來說卻很糟糕。
接近解決方案
因此,讓我們暫停一下并考慮一下我們的需求。
我們需要一些代碼來運(yùn)行并執(zhí)行我們的實(shí)際任務(wù)。
我們需要現(xiàn)有的命令處理循環(huán)才能繼續(xù)工作。
我們需要這兩段代碼同時(shí)工作。
在這個(gè)玩具示例中,第三點(diǎn)是“免費(fèi)”的,因?yàn)闀r(shí)間計(jì)時(shí)器自動(dòng)執(zhí)行等待下一個(gè)計(jì)時(shí)的任務(wù),并且與其余代碼完全并發(fā)。
你真正的代碼很可能不會(huì)有那么奢侈,那么你該怎么辦?
在 Go 中,當(dāng)你需要同時(shí)做某件事和其他事情時(shí),一個(gè)明顯的答案是“使用 goroutine”。
因此,第一步是獲取現(xiàn)有代碼,將其轉(zhuǎn)換為可調(diào)用函數(shù),然后在進(jìn)入循環(huán)之前在單獨(dú)的 goroutine 中調(diào)用它for
。這樣,您將同時(shí)運(yùn)行兩個(gè)部分。
困難的部分
好吧,那并不難。
困難的部分是:
如何配置執(zhí)行任務(wù)的代碼。
如何使單片機(jī)命令處理循環(huán)和執(zhí)行任務(wù)的代碼進(jìn)行通信。
配置
這實(shí)際上取決于您的 $dayjob 或 $current_project 的政策,但有一些提示:
Windows 服務(wù)可以接收命令行參數(shù)——無論是單次運(yùn)行還是永久(在每次運(yùn)行時(shí)傳遞給服務(wù))。
缺點(diǎn)是從 UI/UX 的角度來看使用它們并不方便。
通常 Windows 服務(wù)用于讀取注冊(cè)表。
如今(在 .NET 及其普遍的 xml-ity 出現(xiàn)之后)服務(wù)傾向于讀取配置文件。
大多數(shù)時(shí)候,操作系統(tǒng)環(huán)境并不適合該任務(wù)。
您可以合并其中幾個(gè)場地。
我想我會(huì)從配置文件開始,但話又說回來,我認(rèn)為你應(yīng)該選擇阻力最小的路徑。
需要記住的一件事是,配置的讀取和處理最好在服務(wù)向 SCM 發(fā)出它已啟動(dòng)的信號(hào)之前完成:如果配置無效或無法加載,服務(wù)應(yīng)廣泛記錄該情況并發(fā)出信號(hào)失敗,并且不運(yùn)行實(shí)際的任務(wù)處理代碼。
命令處理循環(huán)和攜帶代碼的任務(wù)之間的通信
在我看來,這是最難的部分。
在這里寫一整本書是可能的,但現(xiàn)在讓我們保持簡單。
為了使其盡可能簡單,我會(huì)執(zhí)行以下操作:
考慮暫停、停止和關(guān)閉幾乎相同:所有這些信號(hào)都必須告訴您的任務(wù)處理代碼退出,然后等待它實(shí)際執(zhí)行此操作。
將“繼續(xù)”信號(hào)視為與啟動(dòng)任務(wù)處理函數(shù)相同:在新的 goroutine 中再次運(yùn)行它。
進(jìn)行單向通信:從控制循環(huán)到任務(wù)處理代碼,而不是其他方式 - 這將大大簡化服務(wù)狀態(tài)管理。
這樣,您可以創(chuàng)建一個(gè)任務(wù)處理代碼偵聽或定期檢查的通道,當(dāng)一個(gè)值來自該通道時(shí),代碼停止運(yùn)行,關(guān)閉通道并退出。
當(dāng) SCM 告訴控制循環(huán)暫停、停止或關(guān)閉時(shí),控制循環(huán)會(huì)在該通道上發(fā)送任何內(nèi)容,然后等待其關(guān)閉。當(dāng)發(fā)生這種情況時(shí),它知道任務(wù)處理代碼已完成。
在 Go 中,僅用于信令的通道的范例是具有類型struct{}
(空struct
)的通道。
如何在運(yùn)行代碼的任務(wù)中監(jiān)視此控制通道的問題是一個(gè)開放的問題,并且在很大程度上取決于它執(zhí)行的任務(wù)的性質(zhì)。
這里的任何進(jìn)一步幫助都可以背誦 Go 書籍中有關(guān)并發(fā)的內(nèi)容,因此您應(yīng)該首先了解這一點(diǎn)。
還有一個(gè)有趣的問題是如何使控制循環(huán)和任務(wù)處理循環(huán)之間的通信能夠適應(yīng)后者可能出現(xiàn)的處理停頓,但話又說回來,在我看來,現(xiàn)在討論這個(gè)問題還為時(shí)過早。
- 1 回答
- 0 關(guān)注
- 180 瀏覽
添加回答
舉報(bào)