我想提出一個交互式的基準程序,在控制檯模式下工作,並希望能夠通過按Ctrl + C或CTRL + BREAK一度中斷當前計算,而隨後的壓制應該照常進行,終止程序。但是,當沒有計算當前正在執行時,首先按Ctrl + C鍵應該會導致終止。刪除Console.CancelKeyPress處理程序,一旦禁用任何處理日後
起初,這看起來像一個簡單的任務。我創建了明顯EnableHandler()
和DisableHandler()
程序靜態類,並與行爲依賴於以前的狀態的處理函數:如果中斷已請求,然後就下臺,並返回,否則設置arg.Cancel
,提高中斷請求標誌。因此,當基準開始時,它啓用處理程序,然後檢查每個主要週期的中斷標誌;完成後,它會禁用處理程序,並根據需要將中斷請求傳播到最上面的調用方。
但是,這種方法只能一次:首次(不管是它曾經解僱與否)去除處理後,重新安裝它之後沒有效果了 - 操作不產生錯誤,但當事件發生時處理程序從不接收控制。這是.NET事件處理的預期行爲嗎?
在SO和其他論壇上有關於Console.CancelKeyPress
的很多主題,但幾乎沒有一個人認爲刪除處理程序,因此毫無疑問,他們沒有遇到麻煩。儘管如此,在「How to use ConsoleCancelEventHandler several times」中提到了一些類似的問題,但是該應用程序是一個複雜的GUI前端,用於根據需要啓動的幾個外部控制檯實用程序,並且該問題顯然與第二次嘗試添加處理程序時引發的顯式異常, - 這不是我的情況。
在被告知安慰各種.NET版本操作相關先前存在的bug,如果這樣的行爲是不正常的,通過.NET故障引起的或特定於Visual Basic,我不會感到驚訝,(我不是確定VB.NET中的AddHandler
和RemoveHandler
是否完全等效於C#中的+=
和-=
事件操作符)。我目前在安裝了所有可用更新的Windows 7 x86-64上使用.NET 4.5和Visual Basic 2012。
作爲一種解決方法,我實際上並不刪除DisableHandler()
例程中的處理程序,而是簡單地切換標誌:當此標誌被清除時,處理程序立即返回,就好像未安裝。但是,這種方法對我來說看起來很難看,我希望通過適當的方式解決問題並實現目標。
PS。由克里斯·達納韋要求當前代碼:
' Usage example
Dim fAbort As Boolean = False
BreakHandler.Enable()
For Each oImplementation As Implementation In oCompetition.Implementations
Benchmark(oImplementation)
If BreakHandler.AbortRequested() Then fAbort = True : Exit For
Next
BreakHandler.Disable()
Return Not fAbort
Public Class BreakHandler
Protected Shared AbortFlag As Boolean = False
Protected Shared HandlerInstalled As Boolean = False
Protected Shared HandlerEnabled As Boolean = False
Public Shared ReadOnly Property AbortRequested() As Boolean
Get
If AbortFlag Then
AbortFlag = False
Return True
Else
Return False
End If
End Get
End Property
Public Shared Sub Enable()
If HandlerEnabled Then Return
If Not HandlerInstalled Then
AddHandler Console.CancelKeyPress, AddressOf Handler
HandlerInstalled = True
End If
HandlerEnabled = True
End Sub
Public Shared Sub Disable()
AbortFlag = False
If Not HandlerEnabled Then Return
' This is where the handler was removed originally.
'RemoveHandler Console.CancelKeyPress, AddressOf Handler
HandlerEnabled = False
End Sub
Protected Shared Sub Handler(ByVal sender As Object, ByVal args As ConsoleCancelEventArgs)
If (Not HandlerEnabled) OrElse AbortFlag Then
Return ' Stand down, allow complete abortion.
Else
Console.Out.WriteLine("Will abort on next cycle. Press Break again to quit.")
AbortFlag = True
args.Cancel = True
End If
End Sub
End Class
你可以發佈一個簡短但完整的程序來演示這個問題嗎?沒有一些代碼,它將很難幫助你。 –