0

我的应用程序有一些长时间运行的方法,需要一些时间才能完成,因此我决定将其推送到单独的任务中,然后显示一些新表单,ShowDialog其中放置沙漏动画,然后在任务完成时关闭此表单。在那一刻的情况是,我的新等待表格根本不会关闭,它只是出现并留下来。我在某处读到它,因为ShowDialog在这种情况下不会返回任何内容,这就是为什么Close在用户在表单上手动单击关闭之前永远不会到达的原因,但是如果我把它放在form.Close它应该与用户单击该表单相同。请解释和支持这里应该改变什么来实现这一点。在我的代码下面。

主要形式:

WinScp = New WinScpOperation("ftp", "myserver", "login", "password", 21, 0)

Dim tsk As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()
   Return WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)
End Function)

Dim pic As New Waiting
pic.ShowDialog() 'show waiting form

Task.WaitAll(tsk) 'waiting on task to be finalized

pic.Close() 'close waiting form
...

等待表格(只有沙漏 gif)

Public Class Waiting
End Class

进一步讨论#1:

选项 1:(您的工作版本)

 Dim pic As New Waiting

                            Dim tsk As Task(Of Boolean) =
    Task.Factory.StartNew(Of Boolean)(
        Function()
            ' Run lenghty task
            Dim Result As Boolean = WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)
            ' Close form once done (on GUI thread)
            pic.Invoke(New Action(Sub() pic.Close()))
            Return Result
        End Function)

                            ' Show the form
                            pic.ShowDialog()
                            Task.WaitAll(tsk)

选项2:(为什么不工作??)

    Dim pic As New Waiting

                            Dim tsk As Task(Of Boolean) =
    Task.Factory.StartNew(Of Boolean)(
        Function()
            ' Run lenghty task
            Dim Result As Boolean = WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)

            Return Result
        End Function)

                            ' Show the form
                            pic.ShowDialog()
                            Task.WaitAll(tsk)
  ' Close form once done (on GUI thread)
            pic.Invoke(New Action(Sub() pic.Close()))

附加问题:

                        Dim pic As New Waiting

                        Dim tsk As Task(Of Boolean) =
Task.Factory.StartNew(Of Boolean)(
    Function()
        ' Run lenghty task
        Dim Result As Boolean = WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)
        ' Close form once done (on GUI thread)
        pic.Invoke(New Action(Sub() pic.Close()))
        Return Result
    End Function)

                        ' Show the form
                        pic.ShowDialog()
                        Task.WaitAll(tsk)

                        If tsk.Result Then 'if return value is true
                            'Do something when file was downloaded correctly
                        Else
                            'Do something when file was NOT downloaded
                        End If

附加#2:这本来是:

           If WinScp.GetFile(lsbxPicPaths.SelectedItem, temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem), False) Then
                temp_pic = temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem)
            End If

我实施了我们的解决方案:

Dim pic As New Waiting


                                Dim tsk As Task(Of Boolean) =
                Task.Factory.StartNew(Of Boolean)(
                   Function()
               Run lenghty task
                      Dim Result As Boolean = WinScp.GetFile(lsbxPicPaths.SelectedItem, temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem), False)
                    ' Close form once done (on GUI thread)
                      pic.Invoke(New Action(Sub() pic.Close()))
                      Return Result
                 End Function)

                           ' Show the form
                              pic.ShowDialog()
                            Task.WaitAll(tsk)

                    If tsk.Result Then 'if return value is true

                                   temp_pic = temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem)
                '                Else

                                End If

                '*************************************

上述解决方案: 不知道为什么在定义两个变量时直接将其放入 GetFile 参数解决它,因为以前也没有变量并且正在工作。有人可以解释这种行为吗?

                Dim remotefile As String = lsbxPicPaths.SelectedItem
                Dim temp_file As String = temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem)


                'http://stackoverflow.com/questions/33030706/put-long-running-method-into-task-showing-new-form-meantime-and-closing-it-once
                Dim pic2 As New Waiting



                Dim tsk2 As Task(Of Boolean) = Task.Factory.StartNew(Of Boolean)(Function()

                                                                                     'Run lenghty task

                                                                                     Dim Result As Boolean = WinScp.GetFile(remotefile, temp_file, False)
                                                                                     'Close form once done (on GUI thread)
                                                                                     pic2.Invoke(New Action(Sub() pic2.Close()))
                                                                                     Return Result
                                                                                 End Function)
                pic2.ShowDialog()
                Task.WaitAll(tsk2)


                If tsk2.Result = True Then
                    MsgBox("GetFile zwrocilo true")
                    temp_pic = temp_dir & "\" & Path.GetFileName(lsbxPicPaths.SelectedItem)
                End If
4

2 回答 2

1

您已经在这里有了答案:
在 WinForm 的进度条上显示 WinSCP .NET 程序集传输进度

简单来说,我只是提取相关部分:

  • 您需要在任务结束时关闭表单。
  • 由于任务在后台线程上运行,您需要使用.Invoke方法来调用 GUI 线程上的关闭。

一个简单的实现如下:

' Create the form before the task, so that we can reference it in the task
Dim pic As New Waiting

Dim tsk As Task(Of Boolean) =
    Task.Factory.StartNew(Of Boolean)(
        Function()
            ' Run lenghty task
            Dim Result As Boolean =
                WinScp.GetFile(myremotePicturePath, ladujZdjeciaPath, True)
            ' Close form once done (on GUI thread)
            pic.Invoke(New Action(Sub() pic.Close()))
            Return Result
        End Function)

' Show the form
pic.ShowDialog()

WinForms 在内部的Form工作方式如下:

Class Form                                      

    Private closed as Boolean                   

    Function ShowDialog                         

        While Not closed                        

            If ' X button clicked                 
                Close                           
            End IF                              

            If ' anything in the Invoke queue     
                ' Get action from the Invoke queue
                ' Run the action                  
                ' In our case the "action" is .Close
            End If                              

            ' Process message queue (mouse clicks, key presses, draw form)

        End While                               

    End Sub                                     

    Sub Close                                   
        closed = True                           
    End Sub                                     

    Sub Invoke(action)                          
        ' Add action to invoke queue              
    End Sub                                     

End Class                                       
于 2015-10-09T06:15:23.460 回答
1

对于没有任务的通用处理程序,这就是我前一段时间在一个应用程序中实现的方式

  1. 添加新表单 (frmProgress)

  2. 将沙漏 GIF 图像 (picProgress) 添加到此表单的中心

  3. 在 GUI 或加载事件的代码中设置以下表单 (frmProgress) 属性:

    Private Sub frmProgress_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load  
        FormBorderStyle = FixedSingle  
        Opacity = 0.5R  
        ShowInTaskbar = False  
        TopMost = True  
        WindowState = Maximized  
    End Sub  
    
  4. 如果需要,在调整大小事件的表格中居中图像

    Private Sub frmProgress_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize  
        picProgress.Left = CInt(Me.Width / 2 - picProgress.Width / 2)  
        picProgress.Top = CInt(Me.Height / 2 - picProgress.Height / 2)  
    End Sub  
    
  5. 在开始处理之前加载表单(不要使用 ShowDialog()

    frmProgress.Show()'DO NOT use ShowDialog()  
    
  6. 开始您的处理

  7. 任务完成后隐藏进度表

    frmProgress.Hide()  
    
于 2015-10-09T06:35:12.367 回答