首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从后台线程打开模式窗体以阻止UI线程,而不同时阻止后台线程

从后台线程打开模式窗体以阻止UI线程,而不同时阻止后台线程
EN

Stack Overflow用户
提问于 2013-06-04 00:06:54
回答 2查看 1.9K关注 0票数 1

也许这是一个简单的问题,我只是不知道正确的搜索词来找到答案,但我的Google-fu在这个问题上让我失败了。

我的vb.net应用程序有一个控制所有套接字通信的后台线程。有时,我需要这个通信线程打开一个模式表单来显示一条消息,并阻止UI交互,直到通信线程完成一系列任务,在这一点上,通信线程将删除模式表单,允许用户继续交互。

目前,我的包含后台线程的通信类有两个事件: StartBlockingTask和EndBlockingTask。我的主窗体有这些事件的事件侦听器,它们调用类似命名的subs。他们把代码叫做这样:

代码语言:javascript
运行
复制
Private Delegate Sub BlockingDelegate(ByVal reason As String)

Private Sub StartBlockingTask(ByVal reason As String)
    If Me.InvokeRequired Then
        Dim del As New BlockingDelegate(AddressOf StartBlockingTask)
        Me.Invoke(del, New Object() {reason})
    Else
        Try
            _frmBlock.lblBlock.Text = reason
            _frmBlock.ShowDialog()
        Catch ex As Exception
            'stuff
        End Try
    End If
End Sub

Private Sub EndBlockingTask()
    If Me.InvokeRequired Then
        Dim del As New BlockingDelegate(AddressOf EndBlockingTask)
        Me.Invoke(del, New Object() {""})
    Else
        Try
            If (Not _frmBlock Is Nothing) Then
                _frmBlock.DialogResult = Windows.Forms.DialogResult.OK
            End If
        Catch ex As Exception
            'stuff
        End Try
    End If
End Sub

这成功地阻止了UI的交互,但也阻止了通信线程,因此EndBlockingTask事件实际上永远不会被引发。如何从通信线程打开此模式对话框,并允许通信线程继续运行?

提前感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-06-04 03:13:36

我不同意。

所有需要做的就是将Invoke()改为BeginInvoke(),您就成功了。

这是因为Invoke()实际上是同步的,这会导致它阻塞,直到ShowDialog()解析为止。

使用BeginInvoke()使其成为异步的,并允许在线程继续的同时阻塞UI:

代码语言:javascript
运行
复制
Public Class Form1

    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        If Not BackgroundWorker1.IsBusy Then
            BackgroundWorker1.RunWorkerAsync()
        End If
    End Sub

    Private Delegate Sub BlockingDelegate(ByVal reason As String)

    Private Sub StartBlockingTask(ByVal reason As String)
        If Me.InvokeRequired Then
            Dim del As New BlockingDelegate(AddressOf StartBlockingTask)
            Me.BeginInvoke(del, New Object() {reason})
        Else
            Try
                _frmBlock.lblBlock.Text = reason
                _frmBlock.ShowDialog()
            Catch ex As Exception
                'stuff
            End Try
        End If
    End Sub

    Private Sub EndBlockingTask()
        If Me.InvokeRequired Then
            Dim del As New BlockingDelegate(AddressOf EndBlockingTask)
            Me.BeginInvoke(del, New Object() {""})
        Else
            Try
                If (Not _frmBlock Is Nothing) Then
                    _frmBlock.DialogResult = Windows.Forms.DialogResult.OK
                End If
            Catch ex As Exception
                'stuff
            End Try
        End If
    End Sub

    Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
        For i As Integer = 1 To 10
            BackgroundWorker1.ReportProgress(i)
            System.Threading.Thread.Sleep(1000)

            If i = 4 Then
                Dim del As New BlockingDelegate(AddressOf StartBlockingTask)
                del("bada...")
            ElseIf i = 7 Then
                Dim del As New BlockingDelegate(AddressOf EndBlockingTask)
                del("bing!")
            End If
        Next
    End Sub

    Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
        Label1.Text = e.ProgressPercentage
    End Sub

End Class
票数 3
EN

Stack Overflow用户

发布于 2013-06-04 00:20:25

您将从创建该地址的子目录中调用该地址。该地址需要从该sub外部调用。

代码语言:javascript
运行
复制
 Private Sub StartBlockingTask(ByVal reason As String)
    If Me.InvokeRequired Then
        Dim del As New BlockingDelegate(AddressOf StartBlockingTask)


   Private Sub EndBlockingTask()
        If Me.InvokeRequired Then
            Dim del As New BlockingDelegate(AddressOf EndBlockingTask)

您需要创建两个代理。一个用于StartBlockingTask,另一个用于EndBlockingTask

这是一个来自MSDN的例子,

代码语言:javascript
运行
复制
Delegate Sub MySubDelegate(ByVal x As Integer)
Protected Sub Test()
   Dim c2 As New class2()
   ' Test the delegate.
   c2.DelegateTest()
End Sub

Class class1
   Sub Sub1(ByVal x As Integer)
      MessageBox.Show("The value of x is: " & CStr(x))
   End Sub
End Class

Class class2
   Sub DelegateTest()
      Dim c1 As Class1
      Dim msd As MySubDelegate
      c1 = New Class1()
      ' Create an instance of the delegate.
      msd = AddressOf c1.Sub1
      msd.Invoke(10) ' Call the method.
   End Sub
End Class

http://msdn.microsoft.com/en-us/library/5t38cb9x(v=vs.71).aspx

如果这有帮助,请告诉我。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16901110

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档