|
用SynchronizationContext异步提取后台数据库的数据的时候是否会有效率差异?
由于数据库比较大,提取的数据也比较多。为了避免用户界面死锁的情况,写了一个DataFetcher的类,通过其来异步从后台数据库提取大量数据。测试发现提取50万的数据需要耗时2小时。但如果不采用异步方式的花,只需要15~30分钟左右。是否异步会有执行效率的差异?求高手看看代码。
- Imports System.Data
- Imports System.ComponentModel
- Imports System.Threading
- Namespace Core
- ''' <summary>
- ''' Provides data for DataFecher.Fetched event.
- ''' </summary>
- Public Class FetchedEventArgs
- Inherits CancelableEventArgs
- Private _data As Object
- ''' <summary>
- ''' Gets the fetched data. Returns null if fetching failed.
- ''' </summary>
- ReadOnly Property Data As Object
- Get
- Return _data
- End Get
- End Property
- ''' <summary>
- ''' Initializes the new instance with data object.
- ''' </summary>
- Friend Sub New(ByVal data As Object)
- MyBase.new()
- _data = data
- End Sub
- End Class
- ''' <summary>
- ''' The delegation which occurs when trying to fetch data asynchronously.
- ''' </summary>
- ''' <param name="cnn">The connection string.</param>
- ''' <param name="cmd">The command text.</param>
- ''' <returns>The data object.</returns>
- Public Delegate Function DataFetchingCallback(ByVal cnn As String, ByVal cmd As String) As Object
- ''' <summary>
- ''' Represents an object which can fetch data asynchronously.
- ''' </summary>
- Public Class DataFetcher
- Private myThread As Thread
- Private _cnn As String
- Private _cmd As String
- Private _context As SynchronizationContext
- Private _fetching As DataFetchingCallback
- ''' <summary>
- ''' Occurs when DataFetcher.Fetch method was completed no matter successfully or failed.
- ''' </summary>
- ''' <param name="sender">The DataFetcher object which raises this event.</param>
- ''' <param name="e">Event data.</param>
- Public Event Fetched(ByVal sender As Object, ByVal e As FetchedEventArgs)
- ''' <summary>
- ''' Gets or sets the asynchronous callback to fetch data.
- ''' </summary>
- Property FetchingHandler As DataFetchingCallback
- Get
- Return _fetching
- End Get
- Set(ByVal value As DataFetchingCallback)
- _fetching = value
- End Set
- End Property
- ''' <summary>
- ''' Gets or sets the connection string for data fetching.
- ''' </summary>
- Property ConnectionString As String
- Get
- Return _cnn
- End Get
- Set(ByVal value As String)
- _cnn = value
- End Set
- End Property
- ''' <summary>
- ''' Gets or sets the command text for data fetching.
- ''' </summary>
- Property CommandText As String
- Get
- Return _cmd
- End Get
- Set(ByVal value As String)
- _cmd = value
- End Set
- End Property
- ''' <summary>
- ''' Indicates whether the DataFetcher is fetching data now.
- ''' </summary>
- ReadOnly Property IsBusy As Boolean
- Get
- Return IsNothing(myThread) = False AndAlso myThread.IsAlive
- End Get
- End Property
- ''' <summary>
- ''' Gets or sets the SynchronizationContext.
- ''' </summary>
- Property Context As SynchronizationContext
- Get
- Return _context
- End Get
- Set(ByVal value As SynchronizationContext)
- _context = value
- End Set
- End Property
- ''' <summary>
- ''' Aborts the data fetching process.
- ''' </summary>
- Sub Abort()
- If Me.IsBusy = False Then Return
- myThread.Abort()
- myThread = Nothing
- Dim e As New FetchedEventArgs(Nothing)
- e.Cancel = True
- e.Message = "Aborted"
- Me.OnFetched(e)
- End Sub
- ''' <summary>
- ''' Checks DataFetcher whether it is ready to be called.
- ''' </summary>
- Protected Sub CheckForIlegal()
- If IsNothing(Me.FetchingHandler) Then
- Throw Exceptions.Create("{0}.FechtingHandler can't be null.", Me.GetType.FullName)
- End If
- If IsNothing(Me.Context) Then
- Throw Exceptions.Create("{0}.Context can't be null.", Me.GetType.FullName)
- End If
- If String.IsNullOrEmpty(Me.ConnectionString) Then
- Throw Exceptions.Create("{0}.ConnectionString can't be empty.", Me.GetType.FullName)
- End If
- If String.IsNullOrEmpty(Me.CommandText) Then
- Throw Exceptions.Create("{0}.CommandText can't be empty.", Me.GetType.FullName)
- End If
- If Me.IsBusy Then
- Throw Exceptions.Create("{0}.Fetch can't be executed when busy.", Me.GetType.FullName)
- End If
- End Sub
- ''' <summary>
- ''' Starts to fetch data asynchronously.
- ''' </summary>
- Sub Fetch()
- Me.CheckForIlegal()
- myThread = New Thread(AddressOf Me.Start)
- Dim ab As New AsyncBody With
- {
- .context = Me.Context,
- .cmd = Me.CommandText,
- .cnn = Me.ConnectionString,
- .fetching = Me.FetchingHandler
- }
- myThread.Start(ab)
- End Sub
- ''' <summary>
- ''' The embeded parameter passed to async thread.
- ''' </summary>
- Private Structure AsyncBody
- ''' <summary>
- ''' The SynchronizationContext which will accept result.
- ''' </summary>
- Public context As SynchronizationContext
- ''' <summary>
- ''' The command text.
- ''' </summary>
- Public cmd As String
- ''' <summary>
- ''' The connection string.
- ''' </summary>
- Public cnn As String
- ''' <summary>
- ''' The delegation of fetching data.
- ''' </summary>
- Public fetching As DataFetchingCallback
- End Structure
- ''' <summary>
- ''' The embeded parameter passed to current thread.
- ''' </summary>
- Protected Structure AsyncResult
- ''' <summary>
- ''' If True, the fetching was failed. Otherwise, False.
- ''' </summary>
- Public cancel As Boolean
- ''' <summary>
- ''' The description of exception.
- ''' </summary>
- Public message As String
- ''' <summary>
- ''' The fetched data object.
- ''' </summary>
- Public result As Object
- End Structure
- ''' <summary>
- ''' Starts to fetch data on an async thread.
- ''' </summary>
- ''' <param name="obj">The AsyncBody object which will be passed DataFetcher.FetchingHandler.</param>
- ''' <remarks/>
- Protected Sub Start(ByVal obj As Object)
- Dim ab = CType(obj, AsyncBody)
- Dim res = New AsyncResult With {.cancel = False, .message = ""}
- Try
- res.result = ab.fetching.Invoke(ab.cnn, ab.cmd)
- Catch ex As Exception
- res.cancel = True
- res.message = ex.Message
- res.result = Nothing
- End Try
- ab.context.Post(AddressOf Me.Post, res)
- End Sub
- ''' <summary>
- ''' Returns current thread to handle fetched data.
- ''' </summary>
- ''' <param name="state">The AsyncResult object which will be used by DataFetcher.FetchedHandler.</param>
- ''' <remarks></remarks>
- Protected Sub Post(ByVal state As Object)
- Dim ar = CType(state, AsyncResult)
- Dim e As New FetchedEventArgs(ar.result)
- e.Cancel = ar.cancel
- e.Message = ar.message
- Me.OnFetched(e)
- End Sub
- ''' <summary>
- ''' Raises DataFetcher.Fetched event.
- ''' </summary>
- Protected Sub OnFetched(ByVal e As FetchedEventArgs)
- RaiseEvent Fetched(Me, e)
- End Sub
- End Class
- End Namespace
复制代码
|
|