It was suggested in a previous post that i should use the Csla.Threading.BackgroundWorker to perform some background tasks, but this doesnt seem to be an option anymore, as i need to about 60+ tasks all at once. I tried to split the tasks up and running 1 at a time, but the Completed event in the Csla.Threading.BackgroundWorker never seems to fire?? bug?? Not sure, will post code below.
I was wondering, that since i have so many tasks, could i use ThreadPool.QueueUserWorkItem?? This seems to offer a good way to queue the tasks up, but when the task is passed to the queue, the ApplicationContext/ClientContext are blank and i need these populating to run my code.
How can i use ThreadPool.QueueUserWorkItem and also ApplicationContext etc?? Anyone know how to copy the values over, or is there a csla.ThreadPool.QueueUserWorkItem??
My code that wasnt firing the Completed event for the BackgroundWorker is as follows. I call the code using
Dim lAsyncProcess as New AsyncProcess(Objects Here)
lAsyncProcess.Run()
----------
Public Class AsyncProcess
Public Class AsyncWorker
Public Report As IBaseReport
Public WaitHandle As AutoResetEvent
Public Sub New(ByVal pReport As IBaseReport, ByVal pWaitHandle As AutoResetEvent)
Report = pReport
WaitHandle = pWaitHandle
End Sub
End Class
Public WaitHandle1 As WaitHandle
Public WaitHandle2 As WaitHandle
Public BuiltReports As Dictionary(Of Integer, IBaseReport)
Public WithEvents BackgroundWorker1 As New Csla.Threading.BackgroundWorker
Public WithEvents BackgroundWorker2 As New Csla.Threading.BackgroundWorker
Public Sub New(ByVal pReports As Dictionary(Of Integer, IBaseReport))
BuiltReports = New Dictionary(Of Integer, IBaseReport)
Dim lLoopCount As Integer
' create wrappers
While lLoopCount < pReports.Count
BuiltReports.Add(pReports.ElementAt(lLoopCount).Value.ReportId, pReports.ElementAt(lLoopCount).Value)
lLoopCount += 1
End While
End Sub
Public Sub Run()
Dim lLoopCount As Integer = 0
Dim lWaitHandles As New List(Of AutoResetEvent)
While lLoopCount < BuiltReports.Count
lWaitHandles.Clear()
lWaitHandles.Add(New AutoResetEvent(False))
BackgroundWorker1.RunWorkerAsync(New AsyncWorker(BuiltReports.ElementAt(lLoopCount).Value, lWaitHandles(0)))
lLoopCount += 1
If lLoopCount < BuiltReports.Count Then
lWaitHandles.Add(New AutoResetEvent(False))
BackgroundWorker2.RunWorkerAsync(New AsyncWorker(BuiltReports.ElementAt(lLoopCount).Value, lWaitHandles(1)))
End If
WaitHandle.WaitAll(lWaitHandles.ToArray)
lLoopCount += 1
End While
End Sub
Public Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork, BackgroundWorker2.DoWork
Dim lAsyncWorker As AsyncWorker = DirectCast(e.Argument, AsyncWorker)
lAsyncWorker.Report.Build()
'lAsyncWorker.WaitHandle.Set()
e.Result = Nothing
End Sub
Public Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted, BackgroundWorker2.RunWorkerCompleted
Dim lAsyncWorker As AsyncWorker = e.Result
Dim lIndex As Integer = 0
While lIndex < BuiltReports.Count
If BuiltReports.ElementAt(lIndex).Value.ReportId = lAsyncWorker.Report.ReportId Then
BuiltReports(lAsyncWorker.Report.ReportId) = lAsyncWorker.Report
lAsyncWorker.WaitHandle.Set()
lIndex = BuiltReports.Count
End If
lIndex += 1
End While
End Sub
End Class
Hi,
In a "rich" client the ApplicationContext is actually storerd in a named slot on the Thread.
The methods required to set the application context is internal in Csla.
You may look into Csla.Threading.Backgroundworker to see how the "object" + ApplicationContext, CultureInfos and User is wrapped in an object and sent to the background thread. The background thread must then make sure to set these on the background thread before calling the actual method. You could use MethodCaller or reflection to call that method on the ApplicationContext (even if it is internal).
Copyright (c) Marimer LLC