![](/img/trans.png)
[英]How can I push the current execution state into a stack so that I can continue from it later?
[英]How do I pause during execution, save state, and continue from same point later on?
我有一個線程正在做一些處理。 我希望能夠在執行期間停止這個線程,以某種方式保存它的位置(以及它正在操作的對象的狀態),然后在以后從那個位置繼續(所以在我的計算機重新啟動之后)。
在 C# 中,這是不可能的,對嗎? 如果沒有,實現此功能的正確設計是什么?
所以我最初的願望是擁有類似的東西
class Foo : Task {
void override Execute(){
//example task
while(someCondition){
...do stuff...
}
}
}
並且能夠在該功能內的任何點暫停/保存。 當功能結束時,每個人都知道它完成了。 作為替代方案,也許這是更好的方法
class Foo : Task {
void override Execute(State previousState){
//set someCondition, other stuff
//IsPaused = false;
previousState.setUpStuff();
//example task
while(someCondition){
...do stuff...
if(base.IsPauseRequested){
base.UpdateState(); //this would be a bit different but just to get the idea
base.IsPaused = true;
return;
}
}
base.RaiseNotifyTaskComplete();
}
}
所以對於需要繼承我的基類的其他人來說,第一種情況要簡單得多,因為他們只需要實現 Execute 函數。 然而,在第二種情況下,他們必須考慮之前的狀態並管理存在良好暫停點的位置。 有一個更好的方法嗎?
你想要的可以通過一個可序列化的狀態機來完成。 基本上,您將局部變量更改為類中的字段,並添加一個保持狀態的字段——原始方法在代碼中的位置。 這個類將是[Serializable]
並且它將有一個方法,比如MoveNext()
,它完成一項工作並返回。 工作時,您在循環中調用此方法。 當你想停止時,你等到當前調用完成,跳出循環,然后將狀態機序列化到磁盤。
根據原始方法的復雜性以及您希望“檢查點”的頻率(當MoveNext()
方法返回時,您可以選擇繼續或不繼續),狀態機可以像只有一個狀態一樣簡單,或者相當復雜。
C# 編譯器在編譯迭代器塊(和 C# 5 的async
方法)時執行非常相似的轉換。 但它不是為了這個目的,它沒有標記生成的類[Serializable]
,所以我認為你不能使用它。 盡管閱讀一些有關如何實際完成此轉換的文章可能會幫助您自己做同樣的事情。
我無法回答C#
,但通常這個問題稱為Persistence並且沒有通用的簡單方法來解決它(除非語言和操作系統提供它)。 您不能就一個線程進行推理,因為您正在考慮的線程正在引用其他一些(全局或堆)數據。 這個問題也與垃圾收集(因為垃圾收集器和持久性機制都傾向於掃描整個活動堆)和數據庫(特別是NoSQL的)有關。 因此,請閱讀有關操作系統的GC 手冊和教科書,另請參閱OSDEV等網站。
另請參閱這份報告草稿,閱讀 Queinnec 的Lisp in Small Pieces一書,並研究現有持久性軟件的源代碼,包括RefPerSys (當然還有Mono ,C# 的開源實現)
當您想要在雲計算環境中保留進程網絡(或圖)時,事情變得更具挑戰性。 然后在網絡上搜索面向代理的編程。
在概念層面上,您的問題與continuation-passing style和callbacks有關,您會發現許多ACM贊助的會議(例如PLDI 、 ISMM )都在該主題上
這可以使用 WF 輕松實現......它具有顯式暫停和恢復任務的所有管道(並且它會為您處理持久性)。 看看這個鏈接。
可能不適合你想要的,但可能值得研究。
您可能可以使用表達式樹或方法鏈設置類似的內容。 為不可中斷的最小“原子”工作單元設置 lambda 或小型方法。 然后,將它們與將按順序執行這些塊中的每一個的“監督者”鏈接在一起,但可以被告知在指令之間停止它正在執行的操作,保存其沿鏈的位置,返回並等待恢復。 如果您想要模式的名稱,您可以將其稱為 Visitor 的變體。
您希望在進程暫停時序列化對象的狀態,然后在它重新啟動后反序列化它。
一個非常簡單的實現是在您的 Task 類 Serialize/Deserialize 上創建兩個靜態方法,它們使用 Linq 在 XML 中讀取/寫入對象的狀態。 當任務暫停時調用 Serialize 將對象作為 xml 轉儲到磁盤,當它重新啟動時調用 Deserialize 讀取 xml。 還有可能更健壯的XmlSerializer類。
無論如何,這是一個復雜的問題,具有概念上簡單的解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.