若只用一個 thread,在執行 fpr_alg_test.exe 或是檔案操作的時候 UI 介面會無法控制(這個 thread 都在處理其他事件來不及回應 UI )
只有 UI thread 可以控制 UI 元件,跨執行續存取 UI 會跳出 exception。
Invoke 是同步呼叫, calling thread 會等到 Invoke 處理完才會繼續、其底層的時作行為是 : 到 UI thread 執行時會先 lock 住 UI thread,等到執行完時才會釋放 lock 。因此某一個 thread 先呼叫了 Invoke 還沒執行完但另外一個 thread 此時也呼叫了 Invoke , 會產生 dead lock。
BeginInvoke 是非同步呼叫,使用到 thread pool 的 thread ,當 BeginInvoke 呼叫時會將 task push 到一個 task queue。此呼叫不會產生像 1 一樣 deadlock 的情況。但一旦將 BeginInvoke 的需求送出就沒有辦法將其 cancel,在關閉 window 或是資料釋放時有可能 task queue 還有未執行的 task ,需要額外用 flag 等控制訊號將其取消或及早 return
- Delegate.Invoke: Executes synchronously, on the same thread.
- Delegate.BeginInvoke: Executes asynchronously, on a threadpool thread.
- Control.Invoke: Executes on the UI thread, but calling thread waits for completion before continuing.
- Control.BeginInvoke: Executes on the UI thread, and calling thread doesn't wait for completion.
- Tim's answer mentions when you might want to use BeginInvoke - although it was mostly geared towards Delegate.BeginInvoke, I suspect.
For Windows Forms apps, I would suggest that you should usually use BeginInvoke. That way you don't need to worry about deadlock, for example - but you need to understand that the UI may not have been updated by the time you next look at it! In particular, you shouldn't modify data which the UI thread might be about to use for display purposes. For example, if you have a Person with FirstName and LastName properties, and you did:
建立 pipe 幫助 C# program 和 C program 可以互相溝通,因此可以直接在 C# pass arguments 給 C program、接到來自 C program 的 output 並將結果顯示在 GUI 介面上
但有以下幾點要注意
不是及時接到對方 process 的 output,實際上是寫到 buffer,等 buffer 寫到一個程度才會更新
當呼叫到 system pause 時,flush 可能會卡住(即便是 flush 指令在 pause 之前),故要特別注意
在 multi-threading 的狀態下,如果關掉 window 只會將 UI thread 結束,此時其他 thread 有可能會在資源釋放後繼續使用,會產生 exception
示意圖如下
解法如下
對應程式碼片段
刪除 mklink 的資料很危險,因此在刪除資料夾的資料時會檢查資料夾是不是 mklink (symbolic link)
經 debug 發現無法重載 Bmp 或刪除 Bmp 是因為 C# 在使用 Bitmap bmp = new Bitmap(path)
時會將其檔案 lock 住,若此時對檔案作存取會直接造成 exception 抑或是直接 crash,因此若要重載或是刪除時必須先使用 bmp.Dispose()
釋放其所用的資源才可