VB.NET后台工作者仍然冻结形式。 [英] VB.NET Background Worker still freezes form.
本文介绍了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
- 您的
BackgroundWorker
启动新线程以提升DoWork
event;DoWork
事件处理程序调用EncryptFiles
;EncryptFiles
方法注意到它在后台线程上运行,而调用调用
将工作移回UI线程;- 在UI线程上继续工作。
解决方案非常简单:
- 删除
InvokeRequired
/从
代码。EncryptFiles
方法调用- 使用
BackgroundWorker
'sReportProgress
方法 [ ^ ]将%进度和文本传递回UI;- 处理
BackgroundWorker
的ProgressChanged
事件 [ ^ ]更新文本和进度条。
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
- Your
BackgroundWorker
kicks off a new thread to raise theDoWork
event;- The
DoWork
event handler callsEncryptFiles
;- The
EncryptFiles
method notices that it's running on a background thread, and callsInvoke
to move the work back to the UI thread;- Work continues on the UI thread.
The solution is fairly simple:
- Remove the
InvokeRequired
/Invoke
code from yourEncryptFiles
method.- Use the
BackgroundWorker
'sReportProgress
method[^] to pass the % progress and text back to the UI;- Handle the
BackgroundWorker
'sProgressChanged
event[^] to update text and progress bar.
这篇关于VB.NET后台工作者仍然冻结形式。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文