我的Delphi應用程序有兩個活動(看起來)必須都出現在UI線程中。在大多數方面,它是一個單線程應用程序。我在這裏有一個問題,因爲我已經使用了Application.ProcessMessages,並且我希望將它最小化,因爲它可能會導致問題。不知道如何解決這個衝突
我將首先描述成分,然後是問題。
應用程序可以打開多個「文檔」表單,但爲了簡單起見,我只能引用一個文檔表單。每種表格都可以與外部設備通信。
有些情況下,可能會出現的情況,其中程序被建立循環,直到設備的某種情況下允許我們退出循環或用戶取消操作。設備接口沒有線程,必須輪詢。
這裏的問題:
當用戶想要關閉文檔,我們可以是在這些循環中的一個。這是一個問題,因爲所有這些都在UI線程中......我沒有一個很好的方法來打破文檔表單中的循環,所以我可以關閉文檔。 (DeviceReady或CancelKeyPressed) Application.ProcessMessages;
原液:
我原來的解決方案是做到以下幾點,當用戶試圖關閉該文檔:
- 發佈用戶的Windows消息文件的形式告訴它我們想關。
- 文檔表單接收到消息並中斷任何活動循環並將消息發送回主窗體,表示我們已準備好關閉。
- 主窗體循環,處理消息和輪詢檢查以查看文檔是否準備關閉。
- 當文檔準備關閉時,它會完成文檔的關閉。
這在大部分時間都適用,但它很複雜 - 尤其是因爲我們一次打開多個文檔。
其他可能的解決方案
,因爲它似乎對我來說,所有這一切都必須出現在主線程,它移動到一個線程不會聽起來像一個解決方案。
曾想過讓文檔異步關閉,但我們需要知道文檔關閉何時完成,因此我們可以讓用戶執行其他操作,如打開另一個文檔。
這些循環相當快; 1)發送「停止」消息2)等待___ ms並處理消息以使其工作3)關閉它。我認爲這將是一個質量較差的設計,可能會很弱。
將此循環轉換爲狀態機。(傳統)設備接口不是線程化的,必須進行輪詢。我需要創建一個線程來執行輪詢並將消息發佈到表單以引發事件。然後,如果發生這樣的事件或按下一個鍵,將發生將導致下一個狀態發生的事件。這樣,如果表格被關閉,它永遠不會成爲問題。遺憾的是,還需要付出努力將周圍的代碼轉換爲參與狀態機。 (這不是一件壞事。)
結論
Application.ProcessMessages似乎是一個藥物...開始使用它&很快你需要更多的使用它!
任何人有任何建議如何更好地處理這種問題?
問題的答案:
(我張貼了這個問題得到一些意見上的方式,我應該與此去,我一個人工作的開發人員,這是一些地方這是有道理的詢問社區對於一些賢者的建議...)
感謝您的意見!
這些「文檔」是如何管理/引用的?
該文件格式是標準的delphi TForm後裔擁有的一個對象列表。
多線程的規則是,如果你需要一個可能導致主線程不響應的連續循環,它應該是一個線程的形式。你爲什麼不允許把它放在別處?爲什麼它必須在主線程中?
問題是整個應用程序需要等待,直到操作完成或用戶取消爲止。我想我可以將所有傳入的密鑰傳遞給線程。當線程看到循環退出條件時,它可以建議UI線程。
我喜歡這種狀態機方法。
所以我...它有一定的優雅和簡單。它也可以簡化一些其他相關係統。
爲什麼不能通過線程與「設備」對話?我會打破用戶界面的這一部分。
可能這就是我應該做的。我需要的唯一調用是線程安全的。
有很多時候人們可能會告訴你,爲了提高性能而將事情轉移到線程中是一種常見的錯誤。但這是你爲什麼應該的一個主要例子。我無法想象任何嚴格要求主UI線程的接口。你是否使用組件放入表單設計器?如果這是你的挫折,你有沒有嘗試過在不同的線程中動態創建這些組件?
組件包括一個功能區,是的,都是從UI線程創建的。假設我無法在另一個線程中安全地創建組件,並將它們放在用戶將與之交互的窗體上。當然,這實際上不會正常工作?
我有足夠的線程經驗,我可以做到這一點,但希望更確定沒有什麼明顯的我失蹤。
由於我看不到您的代碼,因此很難理解。你目前如何執行這個「循環」?這些「文件」是如何管理/引用的?多線程的規則是,如果你需要一個可能導致主線程不響應的連續循環,它應該是一個線程的形式。你爲什麼不允許把它放在別處?爲什麼它必須在主線程中? – 2015-02-07 00:37:03
我喜歡狀態機方法。 – 2015-02-07 01:35:41
爲什麼不能通過線程與「設備」對話?我會打破用戶界面的這一部分。 – Graymatter 2015-02-07 01:52:13