DotNetNewsgroup.com  
web access to complete list of Microsoft.NET newsgroups
   home   |   control panel login   |   archive  |  
 
  carried group
academic
adonet
aspnet
aspnet.announcements
aspnet.buildingcontrols
aspnet.caching
aspnet.datagridcontrol
aspnet.mobile
aspnet.security
aspnet.webcontrols
aspnet.webservices
assignment_manager
datatools
dotnet.distributed_apps
dotnet.general
dotnet.myservices
dotnet.nternationalization
dotnet.scripting
dotnet.security
dotnet.vjsharp
dotnet.vsa
dotnet.xml
dotnetfaqs
framework
framework.clr
framework.compactframework
framework.component_services
framework.controls
framework.databinding
framework.drawing
framework.enhancements
framework.interop
framework.odbcnet
framework.performance
framework.remoting
framework.sdk
framework.setup
framework.webservices
framework.windowsforms
framework.wmi
frwk.windowsforms.designtime
lang.csharp
lang.jscript
lang.vb
lang.vb.controls
lang.vb.data
lang.vb.upgrade
lang.vc
lang.vc.libraries
  
 
start date: Fri, 27 Jul 2007 06:31:51 -0700,    posted on: microsoft.public.dotnet.framework        back       

Thread Index
  1    unknown
          2    Peter Duniho


Threading and WaitAny   
I am encountering a challenge while using WaitAny to detect when any
of my async processes have finished.

The scenario is I have a master class which instantiates two other
classes and calls a method on each asynchronously.  The async method
returns output that is processed via code on the main thread.

So, I have been trying to use the WaitAny passing it an array of the
WaitHandles.  I have this code in a loop that checks to see if we are
done with all async processes.  The problem with this approach is that
after the first async process comes back, and I go back through the
loop to wait for the next async process to finish (using WaitAny
again) - the same async process complete re-fires the same async item
I just processed.

If have also tried to use the AutoResetEvent in the WaitAny event --
But I can figure out how to have the methods being executed
asynchronously in my class object to call the Set method on the
AutoResetEvent to trigger my main thread to continue.

	I have also looked at the internet for some good examples of what I
am trying to do and have been unable to find any -- at least none if
VB code (and I am not too familiar with more complex C# syntax that
would be used in this type of an example.)  If anyone has a good VB
sample that I can refer to, that would be much appreciated.  It not,
the code is below.  This code us currently NOT set to use the
AutoResetEvent for the reason stated above.

Any assistance would be greatly appreciated!!!

 Option Strict On
Option Explicit On

Imports GATSDataSourcesDAL
Imports System.Threading

Public Class AsynTestClass
    Private iobj_GATSDataSource As GATSDAL = Nothing
    Private iobj_GTISDataSource As GTISDAL = Nothing

    'Delegate declarations
    Private Delegate Function ReturnGATSDataSet_Delegate() As DataSet
    Private Delegate Function ReturnGTISDataSet_Delegate() As DataSet

    'Variables to create the delegates
    Private iobj_ReturnGATSDataSet_Delegate As
ReturnGATSDataSet_Delegate
    Private iobj_ReturnGTISDataSet_Delegate As
ReturnGTISDataSet_Delegate

    'Declare the results
    Private iobj_ReturnGATSDataSet_AsyncResults As IAsyncResult
    Private iobj_ReturnGTISDataSet_AsyncResults As IAsyncResult

    Private li_NumberOfDataSources As Integer = 2

    'Declare the WaitHandles Array
    Private ia_WaitHandles(li_NumberOfDataSources - 1) As WaitHandle

    'Documentation says threading items should be called from a Multi-
Threaded Appt
    <MTAThread()> _

    Public Function ReturnDataSet2() As Dictionary(Of String, DataSet)
        'This will return an array of dataset
        Dim ls_ReturnDataSet As DataSet = Nothing
        Dim lb_Done As Boolean = False
        Dim li_DoneCount As Integer
        Dim li_IX As Integer = -1
        Dim la_AsyncResults(li_NumberOfDataSources - 1) As
IAsyncResult
        Dim ls_DataSourceName As String
        Dim lobj_ReturnDictionary As Dictionary(Of String, DataSet) =
New Dictionary(Of String, DataSet)

        'Create the Data Access Layer
        iobj_GATSDataSource = New GATSDAL

        'Create and call the first asyn method
        iobj_ReturnGATSDataSet_Delegate = New
ReturnGATSDataSet_Delegate(AddressOf
iobj_GATSDataSource.ReturnDataSet)

        'Call Async to local DLL to get the data
        iobj_ReturnGATSDataSet_AsyncResults =
iobj_ReturnGATSDataSet_Delegate.BeginInvoke(Nothing, "GATS")

        'Add the async results and waithandles to the array
        li_IX += 1
        la_AsyncResults(li_IX) = iobj_ReturnGATSDataSet_AsyncResults
        ia_WaitHandles(li_IX) =
iobj_ReturnGATSDataSet_AsyncResults.AsyncWaitHandle

        'Create and call the first asyn method
        iobj_GTISDataSource = New GTISDAL

        'Create the proxy class to call the Data Access Layer
        iobj_ReturnGTISDataSet_Delegate = New
ReturnGTISDataSet_Delegate(AddressOf
iobj_GTISDataSource.ReturnDataSet)

        'Call Async to local DLL to get the data
        iobj_ReturnGTISDataSet_AsyncResults =
iobj_ReturnGTISDataSet_Delegate.BeginInvoke(Nothing, "GTIS")

        'Add the async results and waithandles to the array
        li_IX += 1
        la_AsyncResults(li_IX) = iobj_ReturnGATSDataSet_AsyncResults
        ia_WaitHandles(1) =
iobj_ReturnGTISDataSet_AsyncResults.AsyncWaitHandle


        'Wait till all the results are back of the transaction times
out
        Do Until lb_Done = True
            li_IX = WaitHandle.WaitAny(ia_WaitHandles,
TimeSpan.FromSeconds(15), False)

            'Get the correct asyncresults - Use the state to know the
object type
            ls_DataSourceName =
la_AsyncResults(li_IX).AsyncState.ToString

            Select Case ls_DataSourceName
                Case "GATS"
                    'This will get the dataset and raise any errors
                    lobj_ReturnDictionary.Add(ls_DataSourceName,
iobj_ReturnGATSDataSet_Delegate.EndInvoke(la_AsyncResults(li_IX)))
                Case "GTIS"
                    'This will get the dataset and raise any errors
                    lobj_ReturnDictionary.Add(ls_DataSourceName,
iobj_ReturnGTISDataSet_Delegate.EndInvoke(la_AsyncResults(li_IX)))
            End Select

            'Decide if we should end the loop
            li_DoneCount += 1
            If li_DoneCount > ia_WaitHandles.GetUpperBound(0) Then
                lb_Done = True
            End If

        Loop

        Return lobj_ReturnDictionary

    End Function

End Class
Date:Fri, 27 Jul 2007 06:31:51 -0700   Author:  

Re: Threading and WaitAny   
On Fri, 27 Jul 2007 06:31:51 -0700,  wrote:


> I am encountering a challenge while using WaitAny to detect when any
> of my async processes have finished.
>
> The scenario is I have a master class which instantiates two other
> classes and calls a method on each asynchronously.  The async method
> returns output that is processed via code on the main thread.
>
> So, I have been trying to use the WaitAny passing it an array of the
> WaitHandles.  I have this code in a loop that checks to see if we are
> done with all async processes.  The problem with this approach is that> after the first async process comes back, and I go back through the
> loop to wait for the next async process to finish (using WaitAny
> again) - the same async process complete re-fires the same async item
> I just processed.


Things I don't understand about your question:

     * Why are your arrays, ia_WaitHandles and la_AsyncResults, being  initialized to hold one fewer elements than you intend to put in them?  In  this case, those arrays appear to be initialized to only a single element  long.

     * Given the above, why does this line not generate an exception at run-time, seeing how it attempts to set the second element in an array  that's only 1 element long:

          ia_WaitHandles(1) =
              iobj_ReturnGTISDataSet_AsyncResults.AsyncWaitHandle

     * Regardless, why do you hard-code the array index for the handle in  the above line of code, rather than using li_IX as you do elsewhere?

And finally, this statement in your post:


> If have also tried to use the AutoResetEvent in the WaitAny event --
> But I can figure out how to have the methods being executed
> asynchronously in my class object to call the Set method on the
> AutoResetEvent to trigger my main thread to continue.


Even if I replace "I can figure" with "I can't figure" to try to make itmake more sense, I don't understand the statement.  All you need to do is  pass an event handle you create to the delegate doing the work somehow. Passing parameters to delegates isn't hard, so if you're having trouble doing this, you should be more specific about what problem it is you have.

All that said, it seems to me that the most direct way to fix the code  you've got would be to just not wait on handles that have already  completed.  You should be doing this anyway, because once you call  EndInvoke, the wait handle you've put into the array is not guaranteed to  be valid.  But beyond that, not waiting on a wait handle that's always  been completed is the obvious solution to not having to deal with the wait  handle remaining signaled.

An alternative solution would be to simply reset the event handle manually  yourself after it's signaled.  But as I mentioned above, after calling  EndInvoke you are not guaranteed to have a valid event handle, and so  that's not a solution you should choose.  As an alternative to the  alternative, you could just create a dummy WaitHandle (manual or  auto-reset, it doesn't matter) that never gets set and replace the one you  got from the IAsyncResult object with the dummy one, after that  IAsyncResult gets signaled.  IMHO, that solution would be a hack and  inappropriate in any well-written code, but it would work as well.

Pete
Date:Fri, 27 Jul 2007 09:49:28 -0700   Author:  

Google
 
Web dotnetnewsgroup.com


COPYRIGHT ?2005, EUROFRONT WORLDWIDE LTD., ALL RIGHT RESERVE  |   Contact us