CF下的BackgroudWorker组件优化.
.net compact framwork(2.0/3.5)下没有Backgroundworder组件,在网上找了一个类
经过使用发现了一些问题,主要有一个问题:在一个Dowork事件中对ReportProgress 多次输出时可能无法正确完成.
花了点时间对该类进行了修改,将ReportProgress的参数进行队列处理,在实际处理Progress时采用循环检测.用了 Queue功能.
#Region "EventArgs classes"
Public Class RunWorkerCompletedEventArgs
Inherits System.EventArgs
' This class should inherit from AsyncCompletedEventArgs but I don't see the point in the CF's case Private ReadOnly mResult As Object
Private ReadOnly mCancelled As Boolean
Private ReadOnly mError As System.Exception Public Sub New(ByVal aResult As Object, ByVal aError As System.Exception, ByVal aCancelled As Boolean)
mResult = aResult
mError = aError
mCancelled = aCancelled
End Sub Public ReadOnly Property Result() As Object
Get
Return mResult
End Get
End Property Public ReadOnly Property Cancelled() As Boolean
Get
Return mCancelled
End Get
End Property Public ReadOnly Property [Error]() As System.Exception
Get
Return mError
End Get
End Property
End Class Public Class ProgressChangedEventArgs
Inherits System.EventArgs Private ReadOnly mProgressPercent As Int32
Private ReadOnly mUserState As Object Public Sub New(ByVal aProgressPercent As Int32, ByVal aUserState As Object)
mProgressPercent = aProgressPercent
mUserState = aUserState
End Sub Public ReadOnly Property ProgressPercentage() As Int32
Get
Return mProgressPercent
End Get
End Property Public ReadOnly Property UserState() As Object
Get
Return mUserState
End Get
End Property
End Class Public Class DoWorkEventArgs
Inherits System.ComponentModel.CancelEventArgs Private ReadOnly mArgument As Object
Private mResult As Object Public Sub New(ByVal aArgument As Object)
mArgument = aArgument
End Sub Public ReadOnly Property Argument() As Object
Get
Return mArgument
End Get
End Property Public Property Result() As Object
Get
Return mResult
End Get
Set(ByVal value As Object)
mResult = value
End Set
End Property
End Class
#End Region #Region "Delegates for 3 events of class"
Public Delegate Sub DoWorkEventHandler(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Public Delegate Sub ProgressChangedEventHandler(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
Public Delegate Sub RunWorkerCompletedEventHandler(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
#End Region #Region "BackgroundWorker Class"
''' <summary>
''' Executes an operation on a separate thread.
''' </summary>
Public Class BackgroundWorker
Inherits System.ComponentModel.Component #Region "Public Interface"
Public Event DoWork As DoWorkEventHandler
Public Event ProgressChanged As ProgressChangedEventHandler
Public Event RunWorkerCompleted As RunWorkerCompletedEventHandler
Private _eventarg As System.Collections.Generic.Queue(Of ProgressChangedEventArgs)
''' <summary>
''' Initializes a new instance of the BackgroundWorker class.
''' </summary>
Public Sub New()
Me.New(New System.Windows.Forms.Control)
_eventarg = New System.Collections.Generic.Queue(Of ProgressChangedEventArgs)
' ideally we want to call Control.CreateControl()
' without it, running on the desktop will crash (it is OK on the CF)
' [on the full fx simply calling a control's constructor does not create the Handle.] ' The CreateControl method is not supported on the CF so to keep this assembly retargettable
' I have offered the alternative ctor for desktop clients
' (where they can pass in already created controls)
End Sub ''' <summary>
''' Initializes a new instance of the BackgroundWorker class.
''' Call from the desktop code as the other ctor is not good enough
''' Call it passing in a created control e.g. the Form
''' </summary>
Public Sub New(ByVal aControl As System.Windows.Forms.Control)
MyBase.New()
mGuiMarshaller = aControl
End Sub ''' <summary>
''' Gets a value indicating whether the application has requested cancellation of a background operation.
''' </summary>
Public ReadOnly Property CancellationPending() As Boolean
Get
Return mCancelPending
End Get
End Property ''' <summary>
''' Raises the BackgroundWorker.ProgressChanged event.
''' </summary>
''' <param name="aProgressPercent">The percentage, from 0 to 100, of the background operation that is complete. </param>
Public Sub ReportProgress(ByVal aProgressPercent As Int32)
Me.ReportProgress(aProgressPercent, Nothing)
End Sub ''' <summary>
''' Raises the BackgroundWorker.ProgressChanged event.
''' </summary>
''' <param name="aProgressPercent">The percentage, from 0 to 100, of the background operation that is complete. </param>
''' <param name="aUserState">The state object passed to BackgroundWorker.RunWorkerAsync(System.Object).</param>
Public Sub ReportProgress(ByVal aProgressPercent As Int32, ByVal aUserState As Object)
If Not mDoesProgress Then
Throw New System.InvalidOperationException("Doesn't do progress events. You must WorkerReportsProgress=True")
End If
' Send the event to the GUI
_eventarg.Enqueue(New ProgressChangedEventArgs(aProgressPercent, aUserState))
System.Threading.ThreadPool.QueueUserWorkItem( _
New System.Threading.WaitCallback(AddressOf ProgressHelper)) End Sub ''' <summary>
''' Starts execution of a background operation.
''' </summary>
Public Sub RunWorkerAsync()
Me.RunWorkerAsync(Nothing)
End Sub Public ReadOnly Property IsBusy() As Boolean
Get
Return mInUse
End Get
End Property
''' <summary>
''' Starts execution of a background operation.
''' </summary>
''' <param name="aArgument"> A parameter for use by the background operation to be executed in the BackgroundWorker.DoWork event handler.</param>
Public Sub RunWorkerAsync(ByVal aArgument As Object)
If mInUse Then
Throw New System.InvalidOperationException("Already in use.")
End If If DoWorkEvent Is Nothing Then
Throw New System.InvalidOperationException("You must subscribe to the DoWork event.")
End If mInUse = True
mCancelPending = False System.Threading.ThreadPool.QueueUserWorkItem( _
New System.Threading.WaitCallback(AddressOf DoTheRealWork), aArgument)
End Sub ''' <summary>
''' Requests cancellation of a pending background operation.
''' </summary>
Public Sub CancelAsync()
If Not mDoesCancel Then
Throw New System.InvalidOperationException("Does not support cancel. You must WorkerSupportsCancellation=True")
End If mCancelPending = True
End Sub ''' <summary>
''' Gets or sets a value indicating whether the BackgroundWorker object can report progress updates.
''' </summary>
Public Property WorkerReportsProgress() As Boolean
Get
Return mDoesProgress
End Get
Set(ByVal value As Boolean)
mDoesProgress = value
End Set
End Property ''' <summary>
''' Gets or sets a value indicating whether the BackgroundWorker object supports asynchronous cancellation.
''' </summary>
Public Property WorkerSupportsCancellation() As Boolean
Get
Return mDoesCancel
End Get
Set(ByVal Value As Boolean)
mDoesCancel = Value
End Set
End Property
#End Region #Region "Fields"
'Ensures the component is used only once per session
Private mInUse As Boolean 'Stores the cancelation request that the worker thread (user's code) should check via CancellationPending
Private mCancelPending As Boolean 'Whether the object supports cancelling or not (and progress or not)
Private mDoesCancel As Boolean
Private mDoesProgress As Boolean 'Helper objects since Control.Invoke takes no arguments
Private mFinalResult As RunWorkerCompletedEventArgs
Private mProgressArgs As ProgressChangedEventArgs
'Private mProgressArgsList As New List(Of ProgressChangedEventArgs)
' Helper for marshalling execution to GUI thread
Private mGuiMarshaller As System.Windows.Forms.Control
#End Region #Region "Private Methods"
' Async(ThreadPool) called by ReportProgress for reporting progress
Private Sub ProgressHelper()
Dim t As System.Windows.Forms.Control = mGuiMarshaller
t.Invoke(New System.EventHandler(AddressOf TellThemOnGuiProgress))
End Sub ' ControlInvoked by ProgressHelper for raising progress
Private Sub TellThemOnGuiProgress(ByVal sender As Object, ByVal e As System.EventArgs)
Dim o As ProgressChangedEventArgs
While _eventarg.Count >
o = _eventarg.Dequeue()
If o IsNot Nothing Then
RaiseEvent ProgressChanged(sender, o)
End If
End While
End Sub
' Async(ThreadPool) called by RunWorkerAsync [the little engine of this class]
Private Sub DoTheRealWork(ByVal o As Object)
' declare the vars we will pass back to client on completion
Dim er As System.Exception = Nothing
Dim ca As Boolean
Dim result As Object = Nothing ' Raise the event passing the original argument and catching any exceptions
Try
Dim inOut As New DoWorkEventArgs(o)
RaiseEvent DoWork(Me, inOut)
ca = inOut.Cancel
result = inOut.Result
Catch ex As System.Exception
er = ex
End Try ' store the completed final result in a temp var
Dim tempResult As New RunWorkerCompletedEventArgs(result, er, ca) ' return execution to client by going async here
System.Threading.ThreadPool.QueueUserWorkItem( _
New System.Threading.WaitCallback(AddressOf RealWorkHelper), tempResult) ' prepare for next use
mInUse = False
mCancelPending = False
End Sub ' Async(ThreadPool) called by DoTheRealWork [to avoid any rentrancy issues at the client end]
Private Sub RealWorkHelper(ByVal o As Object)
mFinalResult = DirectCast(o, RunWorkerCompletedEventArgs)
mGuiMarshaller.Invoke(New System.EventHandler(AddressOf TellThemOnGuiCompleted))
End Sub ' ControlInvoked by RealWorkHelper for raising final completed event
Private Sub TellThemOnGuiCompleted(ByVal sender As Object, ByVal e As System.EventArgs)
RaiseEvent RunWorkerCompleted(Me, mFinalResult)
End Sub
#End Region
End Class
#End Region
CF下的BackgroudWorker组件优化.的更多相关文章
- JS列表的下拉菜单组件(仿美化控件select)
JS列表的下拉菜单组件(仿美化控件select) 2014-01-23 23:51 by 龙恩0707, 1101 阅读, 6 评论, 收藏, 编辑 今天是农历23 也是小年,在这祝福大家新年快乐!今 ...
- “ShardingCore”是如何针对分表下的分页进行优化的
分表情况下的分页如何优化 首先还是要给自己的开原框架打个广告 sharding-core 针对efcore 2+版本的分表组件,首先我们来快速回顾下目前市面上分表下针对分页常见的集中解决方案 分表解决 ...
- Java多线程21:多线程下的其他组件之CyclicBarrier、Callable、Future和FutureTask
CyclicBarrier 接着讲多线程下的其他组件,第一个要讲的就是CyclicBarrier.CyclicBarrier从字面理解是指循环屏障,它可以协同多个线程,让多个线程在这个屏障前等待,直到 ...
- mac下网页中文字体优化
最近某人吐槽某门户网站在mac下chrome字体超丑,然后发现虽然现在mac用户越来越多,但是大家依然无视mac下的字体差异,于是研究了下mac下网页中的中文字体,和大家分享. 看了一遍国内各大门户和 ...
- 自绘制HT For Web ComboBox下拉框组件
传统的HTML5的下拉框select只能实现简单的文字下拉列表,而HTforWeb通用组件中ComboBox不仅能够实现传统HTML5下拉框效果,而且可以在文本框和下拉列表中添加自定义的小图标,让整个 ...
- Mysql优化系列(1)--Innodb引擎下mysql自身配置优化
1.简单介绍InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的事务安全(ACID兼容)存储引擎.InnoDB锁定在行级并且也在SELECT语句提供一个Oracle风格一致的非锁定读.这些特色 ...
- Google自己的下拉刷新组件SwipeRefreshLayout
SwipeRefreshLayout SwipeRefreshLayout字面意思就是下拉刷新的布局,继承自ViewGroup,在support v4兼容包下,但必须把你的support librar ...
- 在ScrollView下加入的组件,不能自动扩展到屏幕高度
ScrollView中的组件设置android:layout_height="fill_parent"不起作用的解决办法 在ScrollView中添加一个android:fillV ...
- linux 下安装开发组件包
最初安装redhat 时, 系统自己装的,只安装了base 包,在开发过程中,需要不停的安装某个需求包, 图省事,安装光盘下的开发组件包: 在安装光盘下,,,用命令: yum grouplist ...
随机推荐
- Java中的递归原理分析
解释:程序调用自身的编程技巧叫做递归. 程序调用自身的编程技巧称为递归( recursion).递归做为一种算法在程序设计语言中广泛应用. 一个过程或函数在其定义或说明中有直接或间接调用 ...
- Xdebug的使用
1.http://www.cnblogs.com/mo-beifeng/articles/2446142.html 2.http://www.cnblogs.com/ximu/articles/200 ...
- 赋值容器winform 根据NAME查找控件
每日一贴,今天的内容关键字为赋值容器 foreach (Control c in this.panel1.Controls) { if (c is TextBox && c.Name ...
- 用Eclipse来开发STM32
先贴一个官方说明文档:http://www.keil.com/support/man/docs/ecluv/default.htm
- 【M16】谨记80-20法则
1.开始编写代码时,不要过多考虑效率,而应该首先考虑逻辑的清晰性和代码的可读性. 2.后期通过测试找到效率的瓶颈所在,而不是靠猜测.然后,针对性地去解决.也就是80%的时间去解决这20%的代码.
- Swift学习笔记三
协议和扩展 在Objective-C中,协议是很常见也非常重要的一个特性,Swift中也保留了协议,语法略有变化. 用protocol关键字声明一个协议: protocol ExampleProtoc ...
- 设计模式奠基石——UML关系转化为代码
1.继承关系(泛化关系) [说明]:继承关系是子类(派生类)继承父类(基类),或者子接口继承父接口的关系.即子类对象"is a" 父类对象,比方鸟是动物. [UML图]: 图解:A ...
- Android横竖屏切换处理
Android横竖屏要解决的问题应该就两个: 1.布局问题:2.重新载入问题 一.布局问题: 如果不想让软件在横竖屏之间切换,最简单的办法就是在项目的AndroidManifest.xml中找到你 ...
- 设置用户ID和设置组ID
与一个进程关联的ID有6个或更多,如下图所示: 与每个进程相关联的用户ID和组ID 实际用户ID 实际组ID 我们实际是谁 有效用户ID 有效组ID 附加组ID 用于文件访问权限检索 保存的设置用户I ...
- 利用 Composer 一步一步构建自己的 PHP 框架(四)——使用 ORM
本教程示例代码见 https://github.com/johnlui/My-First-Framework-based-on-Composer 回顾 经过前三篇文章 基础准备 . 构建路由 和 设计 ...