Delegate, BeginInvoke. EndInvoke - How to clean up multiple Async threat calls to the same delegate?
I've created a Delegate that I intend to call Async.
Module Level
Delegate Sub GetPartListDataFromServer(ByVal dvOriginal As DataView, ByVal ProgramID As Integer)
Dim dlgGetPartList As GetPartListDataFromServer
The following code I use in a method
Dim dlgGetPartList As New GetPartListDataFromServer(AddressOf AsyncThreadMethod_GetPartListDataFromServer)
dlgGetPartList.BeginInvoke(ucboPart.DataSource, ucboProgram.Value, AddressOf AsyncCallback_GetPartListDataFromServer, Nothing)
The method runs and does what it needs to
The Asyn callback is fired upon completion where I do an EndInvoke
Sub AsyncCallback_GetPartListDataFromServer(ByVal ar As IAsyncResult)
dlgGetPartList.EndInvoke(Nothing)
End Sub
It works as long as the method that starts the BeginInvoke on the delegate only ever runs while there is not a BeginInvoke/Thread operation already r开发者_如何转开发unning. Problem is that the a new thread could be invoked while another thread on the delegate is still running and hasnt yet been EndInvoke'd.
The program needs to be able to have the delegate run in more than one instance at a time if necessary and they all need to complete and have EndInvoke called. Once I start another BeginInvoke I lose the reference to the first BeginInvoke so I am unable to clean up the new thread with an EndInvoke.
What is a clean solution and best practice to overcome this problem?
You only need to hold on to one reference to the delegate; you don't need to create a new one every time you invoke.
Rather than passing Nothing
to EndInvoke
, pass ar
. This will give you the result of that specific invocation.
Sub AsyncCallback_GetPartListDataFromServer(ByVal ar As IAsyncResult)
dlgGetPartList.EndInvoke(ar)
End Sub
If you want to be able to cancel a specific invocation, then you'll want to hold on to the result of BeginInvoke
(which is the same instance of IAsyncResult
that gets passed to you in your callback above).
You need to pass the object as a state argument when you call BeginInvoke.
class Program
{
delegate void SampleDelegate(string message);
static void SampleDelegateMethod(string message)
{
Console.WriteLine(message);
}
static void Callback(object obj)
{
IAsyncResult result = obj as IAsyncResult;
SampleDelegate del = result.AsyncState as SampleDelegate;
del.EndInvoke(result);
Console.WriteLine("Finished calling EndInvoke");
}
static void Main()
{
for (int i = 0; i < 10; i++)
{
// Instantiate delegate with named method:
SampleDelegate d1 = SampleDelegateMethod;
//d1 is passed as a state
d1.BeginInvoke("Hello", Callback, d1);
}
Console.WriteLine("Press any key to continue");
Console.ReadLine();
}
}
精彩评论