2

我有数据记录软件,在导出过程中/之后会在某些机器上冻结。在正常使用期间,主要形式是记录数据。如果用户想要将该数据导出到电子表格,他们会按照步骤打开一个新表单。此表单还保持焦点,直到表单关闭。新表单具有选择要导出的数据集的选项。选择数据集后,用户点击导出按钮。代码很长,但我会尝试总结一下。

Private Sub Exoprt_btn_Click(ByVal...)

Dim fs As FileStream = Nothing
Dim fw As StreamWriter = Nothing
Dim ...

在这个 SQL 东西恰好填写文件之后。这似乎工作正常,因为文件总是打开并正确填充。

在代码的末尾,我们有

fw.Close()
fs.Close()
fw.Dispose()
fs.Dispose()
System.Diagnostics.Process.Start(FileName)

此时,当代码运行时,电子表格将打开,用户可以根据需要保存或关闭。处理完新文件后,他们可以返回弹出窗口,选择要导出的新数据或关闭窗口并使用主窗体。

但是当软件冻结时,返回数据记录程序后,数据导出表单通常是空白的,或者有时按钮和标签等对象会部分加载。导出窗口仍保持焦点,但主窗体仍会随着新数据的记录而更新。尝试关闭导出窗口会导致窗口无响应对话框。重新启动计算机显示后台的所有内容都按预期工作,但无法与窗口的功能进行交互。

我试图通过在睡眠时间和短信中写入来识别恶意代码。

fw.Close()
label1.text = "fw.Close()"
System.Threading.Thread.Sleep(3000)
fs.Close()
label1.text = "fs.Close()"
System.Threading.Thread.Sleep(3000)
...
System.Diagnostics.Process.Start(Filename)
label1.text = "Open File"
System.Threading.Thread.Sleep(3000)

结果是,在关闭 Excel 后,如果程序没有冻结,用户只会看到“打开文件”,如果是,则只会看到“Label1”。

我做了一些研究,并遇到了一些关于线程的想法,因为主窗口是线程化的并且做自己的事情,所以这组代码没有被正确地相互线程化。我不确定为什么有些计算机运行正常而有些计算机似乎一直锁定。

更多实验:

1) 仅打开导出窗口可能会导致窗口在记录时冻结。打开导出窗口后,程序会从 SQL 填充一个类似 datagridview 的对象。

2)我可以在原始实例正在记录时使用另一个记录软件实例来获取数据。这仍然会导致主实例的主窗口锁定。

3) 一台曾经表现出这些症状的电脑似乎已经被它的恶魔驱除。

4

2 回答 2

5

看一下BackgroundWorker类。 这篇文章应该让你开始。要更新您的 label1.Text,请处理ProgressChanged事件并相应地传递进度值。

于 2013-07-16T21:16:51.000 回答
2
  1. 使用导出代码作为函数创建一个类
  2. 在类的顶部创建/添加委托函数 exportHandler
  3. 在您的表单内部,使用导出函数向新类添加一个处理程序。
  4. 创建回调处理程序方法以接收执行导出功能的线程的状态。让回调处理程序调用更新 ui 函数,检查线程是从 UI 运行还是另一个线程。(Me.InvokeRequired 检查这个)
  5. 在 Form btn click 事件内部,使用 targetHandlerExportData 调用调用导出数据异步。

    Private targetHandlerExportData As ClassName.exportHandler = AddressOf objNewClass.exportData
    
    
    Private callbackHandler As AsyncCallback _
                               = AddressOf MyCallbackMethod
    
    
    
    Sub MyCallbackMethod(ByVal ar As IAsyncResult)
        '*** this code fires at completion of each asynchronous method call
        Try
    
            Dim retval As Boolean = targetHandlerExportData.EndInvoke(ar)
            If retval = True Then
                Console.Write(retval)
            End If
            UpdateUI("Task complete")
    
        Catch ex As Exception
            Dim msg As String
            msg = "Error: " & ex.Message
            UpdateUI(msg)
    
        End Try
    End Sub
    
    Sub UpdateUI(ByVal statusMessage As String)
        If Me.InvokeRequired Then
            Dim handler As New UpdateUIHandler(AddressOf UpdateUI_Impl)
            Dim args() As Object = {statusMessage}
            Me.BeginInvoke(handler, args)
    
        Else
            UpdateUI_Impl(statusMessage)
        End If
    End Sub
    
    Delegate Sub UpdateUIHandler(ByVal statusMessage As String)
    
    Sub UpdateUI_Impl(ByVal statusMessage As String)
        Me.sbMain.Panels("Status").Text = statusMessage
    End Sub
                      Private Sub Export_btn_Click()
                      Dim result As IAsyncResult = targetHandlerExportData.BeginInvoke(callbackHandler, Nothing)  
                      End Sub                                                                                                                
    
于 2013-07-23T15:49:28.650 回答