Фоновый рабочий в приложении Excel VSTO, модальный диалог замедляет отмену BGW - PullRequest
1 голос
/ 25 ноября 2011

Я использую фоновый рабочий инструмент в приложении VSTO Excel, чтобы вызвать диалоговое окно хода выполнения со строкой состояния и кнопкой отмены, чтобы избежать длительных вычислений.Это работает очень хорошо, за исключением одного вопроса.Я хотел бы использовать модальное диалоговое окно, чтобы пользовательский интерфейс за диалоговым окном был заблокирован вместо немодального диалога.Если я использую .ShowDialog () вместо .Show (), все будет прекрасно, пока вы не нажмете кнопку «Отмена» в форме.После того, как что-то происходит в отладчике, происходит отмена, которая занимает где-то 30 секунд.Если я использую .Show () в своей форме, то отмена происходит немедленно, как и должно быть.

Я уверен, что пропускаю что-то довольно простое ... Любая помощь будет высоко ценится ...

Private WithEvents BGW As BackgroundWorker
Private PD As ProgressDialog

Public Sub BGW_DoCalculation(Mode As RunMode)
    'Set the Synchronization Context
    System.Threading.SynchronizationContext.SetSynchronizationContext(New WindowsFormsSynchronizationContext())

    'Setup the Background Worker
    BGW = New BackgroundWorker
    BGW.WorkerReportsProgress = True
    BGW.WorkerSupportsCancellation = True

    'Starts the Background Process
    If BGW.IsBusy = False Then
        BGW.RunWorkerAsync(Mode)
    Else
        Exit Sub
    End If

    'Start the Process Dialog Box
    PD = New ProgressDialog
    'Add a handler to cancel background worker
    AddHandler PD.Cancel_Button.Click, AddressOf CancelBackGroundWorker

    PD.ShowDialog()

End Sub


Private Sub CancelBackGroundWorker(sender As Object, e As System.EventArgs)
    BGW.CancelAsync()
End Sub

Private Sub BGW_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BGW.DoWork

    If BGW.CancellationPending = False Then
        Dim Mode As RunMode = CType(e.Argument, RunMode)
        LongRunningCalc(Mode)
    Else
        e.Cancel = True
        Return
    End If

End Sub


Private Sub BGW_WorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BGW.RunWorkerCompleted
    PD.Dispose()
    BGW.Dispose()
End Sub


Private Sub BGW_WorkerProgress(ByVal sender As Object, ByVal e As        System.ComponentModel.ProgressChangedEventArgs) Handles BGW.ProgressChanged
    PD.ProgressBar1.Maximum = 100
    If Not BGW.CancellationPending Then
        PD.ProgressBar1.Value = e.ProgressPercentage
        PD.PercentCompleteLabel.Text = e.ProgressPercentage & "%"
        'Update the message Label
        PD.MessageLabel.Text = e.UserState.ToString
    End If
End Sub

'This is shortened for the posting...
Public Sub LongRunningCalc(ByVal Mode As RunMode)
    'Do long running calc - obviously this isn't the calc ;)
    For i = 0 to 1000000000000000
        i+1
    End For

     If BGW.CancellationPending = True Then
            'Report Progress
            BGW.ReportProgress(CInt(((Scen) / TotalScen) * 100), "Canceling Calculation, Please Wait")
            'Output the scenarios that have been calculated...
            Call Globals.ThisWorkbook.OutScen(Scen, Count)
            Return
        End If
End Sub

Ответы [ 2 ]

1 голос
/ 29 ноября 2011

Я наконец-то после нескольких часов чтения вернулся к посту ниже и реализовал AutoResetEvent

Это ответ, который сработал для меня и позволил избежать любого приложения. Сделайте глупость!

Как ждать отмены BackgroundWorker?

Private _resetEvent As New AutoResetEvent(False)

Private Sub CancelBackGroundWorker(ByVal sender As Object, ByVal e As System.EventArgs)
    BGW.CancelAsync()
    _resetEvent.WaitOne()
End Sub

'This is shortened for the posting...
Public Sub LongRunningCalc(ByVal Mode As RunMode)
'Do long running calc - obviously this isn't the calc ;)
For i = 0 to 1000000000000000
    i+1
End For

 If BGW.CancellationPending = True Then
        'Report Progress
        BGW.ReportProgress(CInt(((Scen) / TotalScen) * 100), "Canceling Calculation, Please Wait")
        'Output the scenarios that have been calculated...
        Call Globals.ThisWorkbook.OutScen(Scen, Count)
            _resetEvent.Set()
        Return
    End If
 _resetEvent.Set()
 End Sub
0 голосов
/ 25 ноября 2011

Уверен, что добавление регулярного вызова в Application.DoEvents поможет вам (я не видел ничего в вашем коде). Клик отмены добавляется в очередь сообщений Windows. Вызов Application.DoEvents явно заставляет приложение обрабатывать ожидающие сообщения очереди.

См. Также: Application.DoEvents

...