Should we always call EndInvoke()?

B

beginwithl

hi

1)
static void Main(string[] args)
{
Delegat delegat = new Delegat( new Program().Async );

IAsyncResult asyncR = delegat.BeginInvoke(null, null);
delegat = new Program().Async1;
IAsyncResult asyncR1 = delegat.BeginInvoke(null, null);


delegat.EndInvoke(asyncR); // exception



}

public void Async()
{
Thread.Sleep(16000);

}


public void Async1()
{
Thread.Sleep(16000);

}


In the above code we invoke delegate “delegat” two times, and thus two
new threads T1 and T2 are created to handle asynchronously invoked
methods. But then a call to EndInvoke() causes an exception to be
raised ( due to passing asyncR instead of asyncR1 as an argument ).


* What is the reason for the decision that EndInvoke() should only be
able to deal with one asynchronously invoked method at the time?


* Why couldn’t object ( of type AsyncResult ) passed as an argument to
EndInvoke() somehow inform it whether it should deal with method in T1
or in T2?


2) “EndInvoke supplies all the output from the asynchronous method
call, including 'ref' and 'out' parameters. If a delegate’s referenced
method has 'ref' or 'out' parameters, they must be
included in EndInvoke’s parameter list before the reference to the
IAsyncResult object,”

Why must we also include 'ref' and 'out' parameters in EndInvoke’s
parameter list?





3) Book claims EndInvoke() also does other things ( disposes thread’s
resources etc ) besides returning the value returned by asynchronously
invoked method, and thus we should always call it even if we are not
interested in a return value. But other sources claim that calling
EndInvoke() is not a must. So which is true?


thank you
 
J

Jesse McGrew

2) “EndInvoke supplies all the output from the asynchronous method
call, including 'ref' and 'out' parameters. If a delegate’s referenced
method has 'ref' or 'out' parameters, they must be
included in EndInvoke’s parameter list before the reference to the
IAsyncResult object,”

Why must we also include 'ref' and 'out' parameters in EndInvoke’s
parameter list?

Because ref/out parameter values are assigned by the method. They're
like extra return values, so you collect them the same way you collect
the return value, by using EndInvoke.

Jesse
 
B

beginwithl

hi


1)
        static void Main(string[] args)
        {
            Delegat delegat = new Delegat( new Program().Async );
            IAsyncResult asyncR = delegat.BeginInvoke(null, null);
            delegat = new Program().Async1;
            IAsyncResult asyncR1 = delegat.BeginInvoke(null, null);
            delegat.EndInvoke(asyncR); // exception
        }
        public void Async()
        {
            Thread.Sleep(16000);
        }
        public void Async1()
        {
            Thread.Sleep(16000);
        }

You should always make sure that when you are posting code with a  
question, it is actual code that will actually compile and run.  
Otherwise, readers have to start making guesses as to what your _real_  
code looks like and what it does.
I apologize about that

Wrong question.  You get the exception not because a delegate can deal  
with only one asynchronous invocation at a time, but rather because you  
_changed_ the delegate instance between the first invocation and the  
second.  The IAsyncResult instance you're passing in goes with a  
completely different delegate than the one you're using to call  
EndInvoke().

* But I’m sure .Net designers could've easily get around this problem
if they thought it would be a good idea that EndInvoke could handle
several asynchronously invoked methods at the same time?!

* Anyways, I assume EndInvoke knows IAsyncResult instance belongs to
another delegate simply by checking AsyncDelegate property ( which is
an instance member of AsyncResult class )?


Assuming you have two IAsyncResult instances from a _single_ object, then 
you could in fact pass either back in a call to EndInvoke(), and the  
delegate instance should correctly match the IAsyncResult to the  
appropriate operation.

But that won’t happened since we can only have one method in
delegate’s invocation list ( assuming we want to make an asynchronous
call )?!


It depends on which EndInvoke() you're talking about.  For a delegate  
instance's BeginInvoke(), you must call that instance's EndInvoke(),  
otherwise you can leak resources.  But for the identically named  
Control.BeginInvoke(), we have it on good authority that the matching call  
to Control.EndInvoke() is _not_ required (I don't have the link handy, but  
this has come up in the past, and someone from Microsoft -- Eric Lippert, 
if I recall correctly -- has said it's unnecessary).

It's possible that both references you're looking at are correct, assuming  
they are talking about different BeginInvoke() and EndInvoke() methods.  
Of course, it's also possible that they are both incorrect, or that one is  
correct and the other is incorrect.  Imposible to say without knowing  
which reference is talking about which BeginInvoke() and EndInvoke()  
methods.

I found an online excerpt from the book Pro C# 2008 and the Net 3.5
platform. It talks about delegate EndInvoke:

“If you asynchronously invoke a method that provides void return
value, you can simply ‘fire and forget’. In such cases, you will never
to cache IAsyncResult-compatible object or call EndInvoke…”


Because the compiler-generated parameter list includes them. It's just
like any other method; you have to pass the arguments that were declared
as part of that method's argument (parameter) list.

Because ref/out parameter values are assigned by the method. They're
like extra return values, so you collect them the same way you collect
the return value, by using EndInvoke.

This is confusing. Say, we pass to asynchronously invoked method a
variable asyncR as a “ref” argument and asyncO as an “out” argument..
Why couldn’t asynchronously invoked method change values of asyncR and
asyncO at the time it is invoked? By having to pass “ref” and “out”
variables to EndInvoke, the code is prone to errors, since we could
instead pass to EndInvoke() variables asyncR1 ( instead of asyncR )
and asyncO1 ( instead of asyncO )?!


thank you both
 
J

Jesse McGrew

This is confusing. Say, we pass to asynchronously invoked method a
variable asyncR as a “ref” argument and asyncO as an “out” argument.
Why couldn’t asynchronously invoked method change values of asyncR and
asyncO  at the time it is invoked? By having to pass “ref” and “out”
variables to EndInvoke, the code is prone to errors, since we could
instead pass to EndInvoke() variables asyncR1 ( instead of asyncR )
and asyncO1 ( instead of  asyncO )?!

BeginInvoke only uses "ref" parameters as inputs, and EndInvoke only
uses "ref" parameters as outputs. So there's no error; it doesn't
matter if you pass a different variable to EndInvoke than you did to
BeginInvoke. The asynchronous method will read in the variable passed
to BeginInvoke and write the new value to the variable passed to
EndInvoke.

The code sample below demonstrates this. Notice that the value of
strR1 doesn't change, and the original value of strR2 is never used.
strO1 is left empty, so the real mystery is why we have to pass "out"
parameters to BeginInvoke!

<code>
using System;

class Program
{
delegate string MyDelegate(ref string refStr, out string outStr);

static string MyMethod(ref string refStr, out string outStr)
{
refStr = "(changed ref) " + refStr;
outStr = "(new out string)";
return "(return value)";
}

static void Main(string[] args)
{
string strR1, strR2, strO1, strO2, strRV;

strR1 = "original strR1";
strR2 = "original strR2";

MyDelegate del = new MyDelegate(MyMethod);
IAsyncResult async = del.BeginInvoke(ref strR1, out strO1,
null, null);
async.AsyncWaitHandle.WaitOne();

strRV = del.EndInvoke(ref strR2, out strO2, async);

Console.WriteLine("strR1: {0}", strR1);
Console.WriteLine("strR2: {0}", strR2);
Console.WriteLine("strO1: {0}", strO1);
Console.WriteLine("strO2: {0}", strO2);
Console.WriteLine("strRV: {0}", strRV);
Console.ReadKey();
}
}
</code>

Jesse
 
B

beginwithl

hi



1)
[...]
* Why couldn’t object ( of type AsyncResult ) passed as an argument to
EndInvoke() somehow inform it whether it should deal with method in T1
or in T2?
Assuming you have two IAsyncResult instances from a _single_ object,
then
you could in fact pass either back in a call to EndInvoke(), and the
delegate instance should correctly match the IAsyncResult to the
appropriate operation.
But that won’t happened since we can only have one method in
delegate’s invocation list ( assuming we want to make an asynchronous
call )?!

Non-sequitur.

First, as far as I can recall, there's no restriction that prevents you
from using BeginInvoke() on a multicast delegate. Depending on the target
methods, it may be difficult to ensure a meaningful result, but it should
work.
If I have two methods registered in delegate's invocation list and if
I call BeginInvoke(), I get an exception saying that delegate must
have only one target.

But even if one was required to only use BeginInvoke() with unicast
delegates, that is not the same as saying that there can only be one
outstanding asynchronous invocation of the delegate at a time. The
invocation list represents the method(s) to call, not the actual calls
themselves.
I realize one can use same delegate instance to asynchronously call a
method M1() several times and thus there can be several M1() “method
instances running” at the same time




2) If I may ask just one more question just to be sure:

From MSDN site on DriveInfo class:
“Any public static members of this type ( DriveInfo class ) are thread
safe. Any instance members are not guaranteed to be thread safe.”

* Are static members thread safe in a sense that you are guaranteed
that no other class in NET library can access and change something
about the drive(s) we are currently inspecting via DriveInfo static
members?

* But why may instance members not be thread safe?


cheers
 
B

beginwithl

hi


Just to be clear: that's the standard boilerplate text found on pretty  
much any .NET class.  In most cases, it appears on classes that don't even  
have static members, or where the static members are trivially thread-safe  
anyway.  :)


Yes and no.  The "thread safe" the documentation is talking about is  
speaking _strictly_ about the class itself.  That is, you can safely call  
static members in the class simultaneously from different threads and  
still get reliable, correct results.  The documentation is not, however,  
making any promises with respect to thread safety about the underlying OS 
object that class represents.

* But do classes in Net library ( ones claiming to be thread safe ),
also guarantee thread safety ( aka giving reliable results ) in cases
where several of these .Net. classes ( each of different type ) try
to, at the same time, access the same resource?

* Do these classes in most cases provide thread safety via locking?

That said, access to the file system is guaranteed thread safety by the OS  
anyway.  But, even that doesn't mean that access to file system objectsis  
blocked for other threads if you have a thread accessing those objects.  
It just means that when more than one thread accesses those objects, the  
OS ensures everything remains coherent, from the _file system's_ point of 
view.
But how can OS guarantee thread safety if it doesn’t block threads
trying to operate on same file system objects?

In the case of the DriveInfo class, this means that the one static member,  
GetDrives(), can be called simultaneously from multiple threads without  
any problem.  But, that doesn't really promise you much.  After all, it's  
essentially a read-only operation anyway, so having multiple threads  
calling that method at once wouldn't really be an issue in any case.
I assume GetDrives() non the less blocks access to the underlying OS
object and that way makes sure that some other static member doesn’t
change that OS object


cheers mate
 
B

beginwithl

hi


No.  Any claim of thread-safety is with respect only to instances of that  
class claiming thread-safety.  And only with respect to a given instance  
(i.e. even multiple instances of the same class are not necessarily  
thread-safe with respect to each other...they are only thread-safe in the 
sense that for any given instance, multiple threads can safely use that  
instance at the same time).

I wasn’t asking about thread safe instances, but more about thread
safe static .Net members. Just like your regular, non-god like
programmer has to make sure that all the different thread-safe
members belonging to different classes have to access same resource in
some synchronized way, I thought the creators ( demigods :D ) of Net
library also made sure that static members from different classes
accessed same resource in some synchronized manner

That said, there are so few instance-thread-safe classes in .NET, that I  
would be surprised to find more than one thread-safe .NET class where a  
single instance uses the same resource as another instance, or as another 
instance of another class.  Have you come across any examples?



Define "block threads trying to operate on same file system objects".  
Being thread-safe doesn't mean that threads are prevented from operating  
on the same objects.  It simply means that when threads do operate on the  
same objects, those operations are synchronized in some way.


That’s what I meant with blocking ( either via locks or in some other
way) … providing synchronized access to the same object


I don't know what you mean.  GetDrives() is a single call.  There is a  
certainly some low-level synchronization to ensure that when you call  
GetDrives(), you do in fact get some reasonable snapshot of the state of  
the system at the very moment that you called it.  But other than that, 
you have no guarantees.  The state could change the instant after that  
call returned, and the data returned would be out of date.

There's no other static member in DriveInfo that could possibly change  
what GetDrives() returns, so asking whether there's any mechanism to  
"block access to the underyling OS object" doesn't make any sense.  It's  
inherently thread-safe, simply due to the fact that nothing else could  
affect it.

Well my question was very much related to my other question about
synchronization between thread-safe static members of different
classes ( when they are all trying to access same resource ).
Afterall, some other Net class may have thread-safe member capable of
changing what GetDrive() returns

thank you
 
B

beginwithl

hi


I have never heard of a class that documents itself as "thread-safe" with 
respect to some _other_ class.  Not that classes couldn't share resources,  
but it's unusual enough for them to do so as it is, never mind for two or 
more classes to claim thread-safety with each other.

One of the points of object-oriented programming is to isolate  
implementation details within a class.  When that's done, different  
classes are automatically thread-safe with respect to each other, because 
they don't interact with each other in a thread-unsafe way.

Despite the ability of classes to isolate implementation details,
there is still possibility of different classes ( those defined in Net
library) trying to operate on same resource at the same time, and if
OS doesn’t synchronize them somehow, then wouldn’t it be possible for
data to get corrupted ( I’m assuming that’s what you meant with the
term “interact with each other in a thread-unsafe way” ) … in other
words, classes would interact with each other in a thread-unsafe way?!


cheers
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top