关于多线程,递归计算问题

ysx10086 2014-01-18 04:28:11
Imports System.ComponentModel
Public Class Form1
'变量定义
Private numberToCompute As Integer = 0
Private highestPercentageReached As Integer = 0
'若要设置后台操作,请为 DoWork 事件添加一个事件处理程序。在此事件处理程序中调用耗时的操作。
'若要启动该操作,请调用 RunWorkerAsync。若要收到进度更新通知,请对 ProgressChanged 事件进行处理。若要在操作完成时收到通知,请对 RunWorkerCompleted 事件进行处理。
'下面的操作就是用来处理消耗时间较多的事件
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
'得到触发该事件的BackGroundWorker的实例
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
'返回表达式显式地转换为指定数据类型、对象、结构、类或接口后的结果
' 将计算结果赋值给DoWorkEventArgs的Result属性。该属性在RunWorkerCompleted的事件处理过程中可见。
e.Result = ComputeFibonacci(e.Argument, worker, e)
'e.Argument=numberToCompute
End Sub

'ComputeFibonacci函数的功能是返回第n项的Fibonacci数
Function ComputeFibonacci(ByVal n As Integer, ByVal worker As BackgroundWorker, ByVal e As DoWorkEventArgs) As Long
' 参数n必须在0到91之间,因为第92项Fibonacci数超出了Long型的表示范围

If n < 0 OrElse n > 91 Then
Return -1
End If
'定义结果变量
Dim result As Long = 0
' 如果用户选择取消操作,即调用了CancelAsync方法,此时CancellationPending属性设置为true。
'因此可以根据CancellationPending属性来判断用于是否取消了操作。之后将DoWorkEventArgs.Cancel标志设为True。
If worker.CancellationPending Then
e.Cancel = True
'如果没有取消,则进行递归计算
Else
MsgBox(n)
If n < 2 Then
result = 1

Else
result = ComputeFibonacci(n - 1, worker, e) + ComputeFibonacci(n - 2, worker, e)
'具体可以看看Fibonacci算法
End If

'报告计算进度
Dim percentComplete As Integer = CSng(n) / CSng(numberToCompute) * 100
MsgBox(percentComplete)
If percentComplete > highestPercentageReached Then
highestPercentageReached = percentComplete
worker.ReportProgress(percentComplete)
End If
End If
'返回计算结果
Return result
End Function

Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As System.Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
'设置进度条
ProgressBar1.Value = e.ProgressPercentage
End Sub

Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If (e.Error IsNot Nothing) Then
'出现异常的情况
lblMessage.Text = e.Error.Message
'被取消的情况
ElseIf e.Cancelled Then
lblMessage.Text = "任务已取消!"
ElseIf e.Result = -1 Then
'参数超出范围的情况
lblMessage.Text = "请输入在0到91之间的整数!"
Else
'任务正常完成的情况
lblMessage.Text = "已完成!结果为" & e.Result.ToString()
End If
txbNum.Enabled = True
btnStart.Enabled = True
btnCancel.Enabled = False
ProgressBar1.Visible = False
End Sub

Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
txbNum.Enabled = False
btnStart.Enabled = False
btnCancel.Enabled = True
lblMessage.Text = "请稍后……"
ProgressBar1.Visible = True
numberToCompute = CInt(Trim(txbNum.Text))
'调用异步操作方法
BackgroundWorker1.RunWorkerAsync(numberToCompute)
End Sub

Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
'调用取消异步操作方法
BackgroundWorker1.CancelAsync()
btnCancel.Enabled = False
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblMessage.Text = ""
ProgressBar1.Visible = False
btnCancel.Enabled = False
BackgroundWorker1.WorkerReportsProgress = True
BackgroundWorker1.WorkerSupportsCancellation = True
End Sub
End Class

下面的代码是如何进行计算的,包括n、result、percentComplete值在程序运行时时怎么变化的?
Function ComputeFibonacci(ByVal n As Integer, ByVal worker As BackgroundWorker, ByVal e As DoWorkEventArgs) As Long
' 参数n必须在0到91之间,因为第92项Fibonacci数超出了Long型的表示范围

If n < 0 OrElse n > 91 Then
Return -1
End If
'定义结果变量
Dim result As Long = 0
' 如果用户选择取消操作,即调用了CancelAsync方法,此时CancellationPending属性设置为true。
'因此可以根据CancellationPending属性来判断用于是否取消了操作。之后将DoWorkEventArgs.Cancel标志设为True。
If worker.CancellationPending Then
e.Cancel = True
'如果没有取消,则进行递归计算
Else
MsgBox(n)
If n < 2 Then
result = 1

Else
result = ComputeFibonacci(n - 1, worker, e) + ComputeFibonacci(n - 2, worker, e)
'具体可以看看Fibonacci算法
End If

'报告计算进度
Dim percentComplete As Integer = CSng(n) / CSng(numberToCompute) * 100
MsgBox(percentComplete)
If percentComplete > highestPercentageReached Then
highestPercentageReached = percentComplete
worker.ReportProgress(percentComplete)
End If
End If
'返回计算结果
Return result
End Function
...全文
152 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
打个比方可能更清楚: 比如说你要给Z发一个邮包,你先给了X,然后X给了Y,然后Y给了Z。结果当你追踪邮包的运送过程,发现,只有当Z收到了邮包以后,才能够显示这个邮包运送过程。 这就是ReportProgroess的问题。它放错了地方。 从这里,你可以分析出“n、result、percentComplete值在程序运行时时怎么变化的”。
  • 打赏
  • 举报
回复
“下面的代码是如何进行计算的,包括n、result、percentComplete值在程序运行时时怎么变化的?” 你贴出的这个代码,其 worker.ReportProgress(percentComplete) 语句的位置是瞎扯的,因此才会经不起使用测试。都递归完毕了,报告进度干什么?应该放到递归的一开始去执行。
  • 打赏
  • 举报
回复
f(n)递归f(n-1)、f(n-2),这只是理论公式而已。 实际计算中,如果f(n-1)内部还会再计算一遍f(n-2),你看有多少次冗余计算?那个浪费的时间是惊人的。

16,549

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧