0

所以基本上我希望我的应用程序运行一个 CPU 密集型方法,同时它应该不断地在不同的表单上显示状态信息。为了防止这种状态表单冻结,我认为将代码外包到一个新线程是一个好主意。

首先,我尝试使用基本线程并调用应该显示状态消息的richtextbox 控件。- 问题是 - 我需要知道线程何时完成才能继续我的主线程。显然,我不能简单地在我的主线程中运行一个循环来不断检查进程是否完成,因为这也会使我的 GUI 冻结。

所以我做了一些研究,发现了关于Tasks的信息。这就是它的外观:

Dim z as new complexProcessClass
Dim taskA = task.Factory.StartNew(Sub() z.start())
taskA.Wait()
If taskA.IsCompleted Then
   MsgBox("finished")
End If

每当进程报告状态时,我都会使用它:

Public Class complexProcessClass
  dim statusWindow as statusForm

  Public Sub start()
    statusWindow = new statusForm
    'complex code here
    reportStatus("bla")
    'complex code here
    reportStatus("blabla")
    'complex code here
  End Sub

  Private Delegate Sub UpdateTextHandler(ByVal Text As String)
  Private Sub reportStatus(Byval s as String)
    If z.RichTextBox1.InvokeRequired Then
      Try
        z.RichTextBox1.Invoke(New UpdateTextHandler(AddressOf xform.RichTextBox1.AppendText), s)
       Catch ex As Exception
                MsgBox(ex.ToString())
       End Try

     Else
        z.RichTextBox1.AppendText(s)
     End If
  End Sub

但它只是在调用调用时一直冻结 - 没有错误消息 - 什么都没有?!

谁能告诉我这样做的正确方法?- 请不要使用背景工作者解决方案;)

提前致谢

4

2 回答 2

0

看一下BackgroundWorker类。这篇文章应该让你开始。

另一种方法是创建委托并异步调用线程并实现更新函数以在工作完成时进行捕获。

  1. 创建一个将工作代码作为函数的类
  2. 在类的顶部创建/添加委托函数处理程序
  3. 在您的表单内部,通过调用您的类方法向新类添加一个处理程序。
  4. 创建回调处理程序方法以接收执行导出功能的线程的状态。让回调处理程序调用更新 ui 函数,检查线程是从 UI 运行还是另一个线程。(Me.InvokeRequired 检查这个)

  5. 在 Form btn click 事件中,使用 targetHandler 调用该方法。

下面的代码是表单代码的样子。


    Public Class Form1
    Private targetHandler As ClassName.Handler = AddressOf objNewClass.somework

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 = targetHandler.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 'Call to your worker thread Private Sub btn_Click() Handles Button1.Click Dim result As IAsyncResult =targetHandler.BeginInvoke(callbackHandler,Nothing) End Sub End Class
于 2013-08-17T18:39:51.490 回答
0

taskA.Wait()您遇到了阻塞 UI 线程的死锁情况,Invoke()内部调用taskA正在等待 UI 线程完成它正在做的事情。这是等待,直到它完成等待。从来没有。

我不完全确定,但试试这个:

Dim taskA = task.Factory.StartNew(Sub() z.start()).ConfigureAwait(False)
于 2013-08-17T22:02:10.690 回答