(1 item) |
|
(1 item) |
|
(5 items) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(6 items) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(4 items) |
|
(2 items) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(2 items) |
|
(5 items) |
|
(3 items) |
|
(1 item) |
|
(1 item) |
|
(1 item) |
|
(3 items) |
|
(1 item) |
|
(1 item) |
|
(2 items) |
|
(8 items) |
|
(2 items) |
|
(7 items) |
|
(2 items) |
|
(2 items) |
|
(1 item) |
|
(2 items) |
|
(1 item) |
|
(2 items) |
|
(4 items) |
|
(1 item) |
|
(5 items) |
|
(1 item) |
|
(3 items) |
|
(2 items) |
|
(2 items) |
|
(8 items) |
|
(7 items) |
|
(3 items) |
|
(7 items) |
|
(6 items) |
|
(1 item) |
|
(2 items) |
|
(5 items) |
|
(5 items) |
|
(7 items) |
|
(3 items) |
|
(7 items) |
|
(16 items) |
|
(10 items) |
|
(27 items) |
|
(15 items) |
|
(15 items) |
|
(13 items) |
|
(16 items) |
|
(15 items) |
A while ago, I got part way through an argument with Roy Osherove, and then got distracted. I finally got back to it, only to discover that comments are now closed on the article in question.
There's a particularly important point I had not gotten around to responding to, so I thought I'd mention it here instead. Roy unfortunately propagates a long-standing myth. It's a particularly persistent myth, which is why I want to talk about it even though this has been public knowledge for over two years now.
As I pointed out to Roy in the comments, if you're writing code that consumes an example of the .NET Async Pattern, every call to BeginWhatever
must to be matched by a corresponding call to EndWhatever
. In fact I quoted from the documentation:
"CAUTION Always call EndInvoke after your asynchronous call completes."
That just refers to Begin/EndInvoke
, but this rule applies to all uses of the async pattern. You must call the EndXxx
method, even if you don't care about the results. (Individual implementations of the async pattern are free to choose to make EndXxx
optional, and to document the fact. But unless the documentation officially says it's OK to omit the call, you should assume that it's required. The only
documented exception to the rule that I'm aware of is in Windows Forms, where you are officially allowed to
call Control.BeginInvoke
without bothering to call Control.EndInvoke
. Not that Microsoft exactly go out of their
way to advertise the fact. Chris Brumme mentions it here in
the comments section of a blog entry, and that's the only official statement I've ever seen. Of course Control.Begin/EndInvoke
isn't
an example of the async pattern either, strictly speaking, as it doesn't support the use of AsyncCallback
... But I digress.)
Roy countered with the popular appeal to authority fallacy. In fact he quotes no lesser authority than Don Box, who said in Essential .NET Volume 1:
"Technically, it is legal to omit the call to EndInvoke if the results of the call are not important."
I know Don believed that to be true when he wrote it. In fact all the .NET instructors at DevelopMentor, myself included, were under the same misapprehension
at the time he wrote that. However I expect that Don is by now well aware that what he wrote there is wrong. (Not that I've not been able to track down a list of errata
for his book.) Bear in mind that I was a DevelopMentor instructor for about six years, and
taught the Essential .NET course on which the book was based
for many years. I well remember the shock when we discovered that EndInvoke
was not in fact optional.
It was a bit of an 'oh crap' moment. We had all been talking about the 'fire and forget' technique with asynchronous delegate invocation in various public forums. Many DevelopMentor instructors had written articles and example code showing the technique, and we had all described it in class. And of course it was in Don's book by then too. So when Microsoft eventually remembered to let the outside world know that this technique is not in fact legal, it was rather astonishing.
Ever since, all of DevelopMentor's .NET instructors have been trying to undo the damage. (I think this was the first public statement after the internal discussions.) Evidently the
damage was extensive - as Roy's article shows, plenty of people still believe it's OK to omit the call to EndInvoke
. It's not. Don's
undoubtedly an incredibly smart guy, but even he isn't omniscient. And I think he would bow to Chris Brumme's knowledge of the CLR. The fact
is, EndInvoke
is not optional. Microsoft obviously have the right to relax this requirement in the future if they want to, but for now,
you have to call EndInvoke
.
As far as I'm aware, adding [OneWay]
doesn't help. Someone suggested that in the comments of Chris Brumme's article
on the subject, but there doesn't seem to be a reply. There is nothing in the documentation to suggest that it will.
(P.S., this is not the only important point I disagree with in that article. For example, I think that it's almost always going to be a bad idea to use asynchronous delegate invocation to raise events. This would be a total disaster if you ever used the event source in a Windows Forms application, for example. But I'll leave that to another time.)