VB.NET后台工作者仍然冻结形式。 [英] VB.NET Background Worker still freezes form.

查看:63
本文介绍了VB.NET后台工作者仍然冻结形式。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好,



你能帮我解决这个问题。 Backgroundworker应该使表单响应,但我的代码没有这样做。以下代码是否有问题。



 私人 代表  Sub  EncyptFilesDelegate()

私有 Sub EncyptFiles()
如果 .InvokeRequired < span class =code-keyword>然后
.Invoke( New EncyptFilesDelegate( AddressOf EncyptFiles), 对象(){})
否则
' 更多代码(声明,创建文件夹等)
对于 每个文件名作为 String frmMain.OpenFileDialog1.FileNames
FileCrypt(Filename,save&文件夹(索引)& \& file,UniqueID,Crypt.CryptAction.Encrypt)
下一步
结束 如果
结束 Sub

私有 Sub FileCrypt( ByVal InputFile 作为 字符串 ByVal OutputFile 作为 字符串 ByVal 密码作为 字符串 ByVal 方向 As Crypt.CryptAction)
' 更多代码(声明,获取密钥,等)
如果 Direction = Crypt.CryptAction.Encrypt 那么
CryptoStream = Security.Cryptography.CryptoStream(Output,Rijndael.CreateEncryptor(Key,IV),Security.Cryptography.CryptoStreamMode.Write)
Else
CryptoStream = Security.Cryptography.CryptoStream(输出,Rijndael.CreateDecryptor(Key,IV),Security.Cryptography.CryptoStreamMode.Write)
结束 如果
Dim persecond 作为 = 0
Dim watch 作为 秒表
观看。开始()
处理& LT; FileLength
CurrentBlock = Input.Read(Buffer, 0 4096
CryptoStream .Write(Buffer, 0 ,CurrentBlock)
已处理=已处理+ CLng (CurrentBlock)
' PROGRESSBAR
TotalProcessed = TotalProcessed + CLng (CurrentBlock)
如果 watch.ElapsedMilliseconds> 1000 然后
ProgressBar1.Value = CInt ((TotalProcessed / TotalLength)* 100
Me .Text = CInt ((TotalLength - TotalProcessed)/ persecond)& 剩余秒数
persecond = 0
watch.Restart()
结束 如果
persecond = persecond + CLng (CurrentBlock)
结束 while
watch。 Stop ()
CryptoStream.Close()
Input.Close()
Output.Close()
结束 Sub

私有 Sub BackgroundWorker1_DoWork(发件人 As 对象,e As System.ComponentModel.DoWorkEventArgs)句柄 BackgroundWorker 1.DoWork
如果 Action = ProgressAction.Encypt 那么
Dim encypt As EncyptFilesDelegate = AddressOf EncyptFiles
encypt .Invoke()
MsgBox( 完成
结束 如果
结束 Sub



我尝试将 FileCrypt 放在 EncyptFiles 但结果相同。



谢谢...

解决方案

原因应该是相当明显的:

 私人  Sub  EncyptFiles()
如果 .InvokeRequired 然后
.Invoke(< span class =code-keyword>新 EncyptFilesDelegate( AddressOf EncyptFiles), < span class =code-keyword> Object (){})
Else
' 更多代码(声明,创建文件夹等)
对于 每个文件名作为 字符串 In frmMain.OpenFileDialog1.FileNames
FileCrypt(Filename,save&文件夹(索引)& \& file,UniqueID,Crypt.CryptAction.Encrypt)
下一步
结束 如果
结束 Sub





  1. 您的 BackgroundWorker 启动新线程以提升 DoWork event;
  2. DoWork 事件处理程序调用 EncryptFiles ;
  3. EncryptFiles 方法注意到它在后台线程上运行,而调用调用将工作移回UI线程;
  4. 在UI线程上继续工作。





解决方案非常简单:


Hello Everyone,

Can you help me with this one. Backgroundworker should make the Form responsive but my code is not doing that. Is there something wrong with the below code.

Private Delegate Sub EncyptFilesDelegate()

Private Sub EncyptFiles()
    If Me.InvokeRequired Then
        Me.Invoke(New EncyptFilesDelegate(AddressOf EncyptFiles), New Object() {})
    Else
        'MORE CODE (Declaration, Create Folder, etc)
        For Each Filename As String In frmMain.OpenFileDialog1.FileNames
            FileCrypt(Filename, save & folders(Index) & "\" & file, UniqueID,  Crypt.CryptAction.Encrypt)
        Next
    End If
End Sub

Private Sub FileCrypt(ByVal InputFile As String, ByVal OutputFile As String, ByVal Password As String, ByVal Direction As Crypt.CryptAction)
    'MORE CODE (Declaration, Getting Key, etc)
    If Direction = Crypt.CryptAction.Encrypt Then
        CryptoStream = New Security.Cryptography.CryptoStream(Output, Rijndael.CreateEncryptor(Key, IV), Security.Cryptography.CryptoStreamMode.Write)
    Else
        CryptoStream = New Security.Cryptography.CryptoStream(Output, Rijndael.CreateDecryptor(Key, IV), Security.Cryptography.CryptoStreamMode.Write)
    End If
    Dim persecond As Long = 0
    Dim watch As New Stopwatch
    watch.Start()
    While Processed < FileLength
        CurrentBlock = Input.Read(Buffer, 0, 4096)
        CryptoStream.Write(Buffer, 0, CurrentBlock)
        Processed = Processed + CLng(CurrentBlock)
        'PROGRESSBAR
        TotalProcessed = TotalProcessed + CLng(CurrentBlock)
        If watch.ElapsedMilliseconds > 1000 Then
            ProgressBar1.Value = CInt((TotalProcessed / TotalLength) * 100)
            Me.Text = CInt((TotalLength - TotalProcessed) / persecond) & " seconds remaining"
            persecond = 0
            watch.Restart()
        End If
        persecond = persecond + CLng(CurrentBlock)
    End While
    watch.Stop()
    CryptoStream.Close()
    Input.Close()
    Output.Close()
End Sub

Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
    If Action = ProgressAction.Encypt Then
        Dim encypt As EncyptFilesDelegate = AddressOf EncyptFiles
        encypt.Invoke()
        MsgBox("Done")
    End If
End Sub


I try putting the FileCrypt inside the EncyptFiles but same result.

Thanks...

解决方案

The reason should be fairly obvious:

Private Sub EncyptFiles()
    If Me.InvokeRequired Then
        Me.Invoke(New EncyptFilesDelegate(AddressOf EncyptFiles), New Object() {})
    Else
        'MORE CODE (Declaration, Create Folder, etc)
        For Each Filename As String In frmMain.OpenFileDialog1.FileNames
            FileCrypt(Filename, save & folders(Index) & "\" & file, UniqueID,  Crypt.CryptAction.Encrypt)
        Next
    End If
End Sub



  1. Your BackgroundWorker kicks off a new thread to raise the DoWork event;
  2. The DoWork event handler calls EncryptFiles;
  3. The EncryptFiles method notices that it's running on a background thread, and calls Invoke to move the work back to the UI thread;
  4. Work continues on the UI thread.



The solution is fairly simple:

  • Remove the InvokeRequired / Invoke code from your EncryptFiles method.
  • Use the BackgroundWorker's ReportProgress method[^] to pass the % progress and text back to the UI;
  • Handle the BackgroundWorker's ProgressChanged event[^] to update text and progress bar.


这篇关于VB.NET后台工作者仍然冻结形式。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆