バックグラウンドワーカーとフォームに問題があります。
私は、ワーカーイベントRunWorkerCompletedでme.closeを呼び出そうとしていますが、myform.Designer.vbファイルのオーバーライドされた "Dispose" SubでStackOverflow例外が発生します。
「新しい」コンストラクタが必要なためにオーバーロードされる前に少し時間がかかりましたが、今はいつもStackOverflow例外が発生しますが、理由はわかりません。 デザイナーファイルは変更していませんが、前のコードを使用しても失敗しません。 一時的な解決策としてスタックサイズを増やすことはできますか? これは競合状態の結果ですか? 私はまた、バックグラウンドプロセスの優先度を上げ、UIを低くしてみました。System.ComponentModel.BackgroundWorker.RunWorkerCompletedからWinFormを閉じるときにvb.netでSystem.StackOverflowExceptionが発生する
次のように私のフォームのコードは次のとおりです。
Public Class frmProgreso
Private elImpresionCancelada As Boolean
Private WithEvents miWorker As System.ComponentModel.BackgroundWorker
Private miListaReports As Report.EnumNombreReport()
Private miListaReportsStr As String(,)
Private miInforme_ruta As String
Private miEmpresa As String
Private miAño As Integer
Private miMes As Integer
Private oReport As Report
Private lasCategorias As String()
Private got_closing_order As Boolean = False
Public Sub New(ByVal ListaReports As Report.EnumNombreReport(), ByVal Empresa As String, ByVal Año As Integer, ByVal Mes As Integer, ByVal OpcionMenu As String, ByVal Categorias As String())
' Llamada necesaria para el diseñador.
InitializeComponent()
' Agregue cualquier inicialización después de la llamada a InitializeComponent().
miEmpresa = Empresa
miAño = Año
miMes = Mes
lasCategorias = Categorias
miListaReports = ListaReports
ReiniciarInformes(0)
ReiniciarCeldas(0)
lblOpcionMenu.Text = OpcionMenu
End Sub
Public Sub New(ByVal informes As String(,), ByVal Empresa As String, ByVal Año As Integer, ByVal Mes As Integer, ByVal OpcionMenu As String, ByVal Categorias As String())
' Esta llamada es exigida por el diseñador.
InitializeComponent()
' Agregue cualquier inicialización después de la llamada a InitializeComponent().
miEmpresa = Empresa
miAño = Año
miMes = Mes
lasCategorias = Categorias
miListaReportsStr = informes
ReiniciarInformes(0)
ReiniciarCeldas(0)
lblOpcionMenu.Text = OpcionMenu
End Sub
Public Sub New(ByVal ruta_completa_informe As String, ByVal Empresa As String, ByVal Año As Integer, ByVal Mes As Integer, ByVal OpcionMenu As String, ByVal Categorias As String())
' Esta llamada es exigida por el diseñador.
InitializeComponent()
' Agregue cualquier inicialización después de la llamada a InitializeComponent().
miEmpresa = Empresa
miAño = Año
miMes = Mes
lasCategorias = Categorias
miInforme_ruta = ruta_completa_informe
ReiniciarInformes(0)
ReiniciarCeldas(0)
lblOpcionMenu.Text = OpcionMenu
End Sub
Public ReadOnly Property ProcesoCancelado() As Boolean
Get
Return elImpresionCancelada
End Get
End Property
Public Sub ImprimirDesdeCatalogo(Optional ByVal informes As String(,) = Nothing)
If Not IsNothing(informes) Then
miListaReportsStr = informes
End If
Me.Show()
LanzarImpresion()
End Sub
Public Sub ReiniciarCeldas(ByVal NumeroCeldas As Integer)
pbCeldas.Minimum = 0
pbCeldas.Maximum = NumeroCeldas
pbCeldas.Value = pbCeldas.Minimum
pbCeldas.Step = 1
lblCeldas.Text = String.Empty
End Sub
Public Sub ReiniciarInformes(ByVal NumeroInformes As Integer)
pbInformes.Minimum = 0
pbInformes.Maximum = NumeroInformes * 3 'Para cada informe, se realizan tres pasos: carga de plantilla en array, procesamiento de celdas y carga de array en plantilla
pbInformes.Step = 1
pbInformes.Value = pbInformes.Minimum
lblInforme.Text = String.Empty
End Sub
'Private Sub frmProgreso_FormClosing(sender As Object, e As FormClosingEventArgs) Handles Me.FormClosing
' If miWorker.IsBusy() Then
' got_closing_order = True
' miWorker.CancelAsync()
' e.Cancel = True
' Me.Enabled = False
' Return
' End If
' MyBase.OnFormClosing(e)
'End Sub
Private Sub frmProgreso_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.WindowState = FormWindowState.Maximized
CentrarObjeto(gbPrincipal)
End Sub
Private Sub miWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles miWorker.DoWork
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.RealTime
If Not IsNothing(miListaReportsStr) Then
'Proceso nuevo.
miWorker.ReportProgress((UBound(miListaReportsStr, 1)) * 3, "INICIAR INFORMES") 'Para cada informe, se realizan tres pasos: carga de plantilla en array, procesamiento de celdas y carga de array en plantilla
For i As Integer = 0 To UBound(miListaReportsStr, 1) - 1
If miWorker.CancellationPending Then
Exit For
End If
'miWorker.ReportProgress(1, miListaReports.ElementAt(i).ToString)
oReport = New Report(miListaReportsStr(0, i), miEmpresa, miAño, miMes, miWorker, cRutaBase_InformesXLSGenerados, lasCategorias, miListaReportsStr(1, i))
oReport.Imprimir(txtCeldaValidacion.Text.Trim)
Next
ElseIf miInforme_ruta <> "" Then
'proceso nuevo fichero individual
miWorker.ReportProgress(3, "INICIAR INFORMES") 'Para cada informe, se realizan tres pasos: carga de plantilla en array, procesamiento de celdas y carga de array en plantilla
'miWorker.ReportProgress(1, miListaReports.ElementAt(i).ToString)
oReport = New Report(miInforme_ruta, miEmpresa, miAño, miMes, miWorker, cRutaBase_InformesXLSGenerados, lasCategorias)
oReport.Imprimir(txtCeldaValidacion.Text.Trim)
Else
'Proceso Antiguo
miWorker.ReportProgress(miListaReports.Length * 3, "INICIAR INFORMES") 'Para cada informe, se realizan tres pasos: carga de plantilla en array, procesamiento de celdas y carga de array en plantilla
For i As Integer = 0 To miListaReports.Length - 1
If miWorker.CancellationPending Then
Exit For
End If
'miWorker.ReportProgress(1, miListaReports.ElementAt(i).ToString)
oReport = New Report(miListaReports.ElementAt(i), miEmpresa, miAño, miMes, miWorker, cRutaBase_InformesXLSGenerados, lasCategorias)
oReport.Imprimir(txtCeldaValidacion.Text.Trim)
Next
End If
End Sub
Private Sub miWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles miWorker.ProgressChanged
If e.UserState = "INICIAR CELDAS" Then
pbCeldas.Minimum = 0
pbCeldas.Maximum = e.ProgressPercentage
pbCeldas.Value = pbCeldas.Minimum
pbCeldas.Step = 1
lblCeldas.Text = String.Empty
ElseIf e.UserState = "INCREMENTAR CELDAS" Then
pbCeldas.Value = pbCeldas.Value + 1
lblCeldas.Text = "Calculando celda " & pbCeldas.Value & "/" & pbCeldas.Maximum
'If pbCeldas.Value = 9811 Then
' MessageBox.Show("1")
'End If
ElseIf e.UserState = "LEER CELDAS PLANTILLA" Then
pbCeldas.Value = pbCeldas.Value + 1
lblCeldas.Text = "Leyendo plantilla celda " & pbCeldas.Value & "/" & pbCeldas.Maximum
ElseIf e.UserState = "VOLCAR CELDAS PLANTILLA" Then
pbCeldas.Value = pbCeldas.Value + 1
lblCeldas.Text = "Escribiendo en plantilla celda " & pbCeldas.Value & "/" & pbCeldas.Maximum
ElseIf e.UserState = "INICIAR INFORMES" Then
pbInformes.Minimum = 0
pbInformes.Maximum = e.ProgressPercentage
pbInformes.Value = pbInformes.Minimum
pbInformes.Step = 1
lblInforme.Text = String.Empty
Else
lblInforme.Text = "Imprimiendo... < " & e.UserState & " > (Fase " & (pbInformes.Value Mod 3) + 1 & "/3)" '
pbInformes.Value = pbInformes.Value + e.ProgressPercentage
End If
End Sub
Private Sub frmImportarInformesExcel_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
CentrarObjeto(gbPrincipal)
End Sub
Private Sub butCancelarImpresion_Click(sender As System.Object, e As System.EventArgs) Handles butCancelarImpresion.Click
If MessageBox.Show("¿Estás seguro de que deseas cancelar la impresión?", "Cancelar impresión", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) = Windows.Forms.DialogResult.Yes Then
elImpresionCancelada = True
If oReport IsNot Nothing Then
oReport.CancelarImpresion = True
End If
If miWorker IsNot Nothing Then
miWorker.CancelAsync()
End If
'Me.Close()
Me.Hide()
End If
End Sub
Private Sub LanzarImpresion()
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.Processpriorityclass.BelowNormal
butComenzar.Enabled = False
txtCeldaValidacion.Enabled = False
lblInforme.Visible = True
lblCeldas.Visible = True
pbCeldas.Visible = True
pbInformes.Visible = True
lblOpcionMenu.Visible = False
miWorker = New System.ComponentModel.BackgroundWorker()
miWorker.WorkerReportsProgress = True
miWorker.WorkerSupportsCancellation = True
miWorker.RunWorkerAsync()
End Sub
Private Sub butComenzar_Click(sender As System.Object, e As System.EventArgs) Handles butComenzar.Click
LanzarImpresion()
End Sub
Private Sub miWorker_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles miWorker.RunWorkerCompleted
' a veces no se puede cerrar al usar el debugger... parece un error por utilizar hilos. ç
miWorker.CancelAsync()
miWorker.Dispose()
miWorker = Nothing
System.Diagnostics.Process.GetCurrentProcess().PriorityClass = System.Diagnostics.ProcessPriorityClass.Normal
Me.Dispose(False)
End Sub
Private Sub txtCeldaValidacion_LostFocus(sender As Object, e As EventArgs) Handles txtCeldaValidacion.LostFocus
txtCeldaValidacion.Text = Replace(Replace(Replace(txtCeldaValidacion.Text, " ", ""), ":", ""), "$", "")
End Sub
End Class
編集1: 私は、コールスタックを見しようとしてきたと、はい、スタックオーバーフローがfrmprogreso上のDisposeメソッドのであり.designer.vbは何度も呼ばれています。 Effective stack overflow
しかし、私が見ることができるように、ユーザコード側からそれは一度だけ呼ばれています
...
Only one call from user code side
Dispose()メソッドにブレークポイントを設定します。 2度目のヒットになると、コールスタックデバッガウィンドウの内容に興味を持っているはずです。あなたがそれを理解できなければ、その内容を投稿してください。 –
何らかの理由で自動生成コードを変更しました。 'Me.Dispose'は、' MyBase.Dispose'だった致命的な間違いです。これがどのように起こったのか推測するのは難しいでしょう。 –