Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / New Users / March 2008

Tip: Looking for answers? Try searching our database.

Anyone from Microsoft confirm this bug or explain this as feature

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Aamir Mahmood - 21 Mar 2008 07:54 GMT
I have posted this issue earlier on
microsoft.public.dotnet.languages.csharp, but nobody replied to that.

Consider following code:

--------------------------------------------------------------------------------

private void button1_Click(object sender, EventArgs e) {
   using (System.Transactions.TransactionScope tx = new TransactionScope())
{
       System.Transactions.Transaction.Current.TransactionCompleted += new
TransactionCompletedEventHandler(Current_TransactionCompleted);

       System.Console.WriteLine(System.Threading.Thread.CurrentThread.GetHashCode());
// prints 4, could be different on your machine
       throw new Exception();

       tx.Commit();
   }
}

private void Current_TransactionCompleted(object sender,
TransactionEventArgs e) {
   System.Console.WriteLine(System.Threading.Thread.CurrentThread.GetHashCode());
//  prints 6, could be different on your machine
}

--------------------------------------------------------------------------------

The problem is the output, first it outputs 4, and it ouputs 6 (it can be a
different output on your machine).

I have various fields with [ThreadStatic] attribute.  Since the
TransactionCompleted is coming on a different thread, it is making all those
[ThreadStatic] fields useless.
This is driving me crazy.

The event MUST be fired on the same thread that created TransactionScope and
subscribed this event.
But the Microsoft implemented in a way, that the initial thread is stopped
and a different thread is used to fire the event (WHY???).  After the event
handler function finishes, application continues with the original thread.
WHY EVENT IS FIRED ON A DIFFERENT THREAD?  I have [ThreadStatic] members
which I cannot use.
I have cleanup routines which were tied to that specific transactions
created for that specific thread.

Since this is not explained in any documentation, I think it is a bug.

Thanks.

AM.
Jon Skeet [C# MVP] - 21 Mar 2008 09:40 GMT
<snip>

> The problem is the output, first it outputs 4, and it ouputs 6 (it can be a
> different output on your machine).
>
> I have various fields with [ThreadStatic] attribute.  Since the
> TransactionCompleted is coming on a different thread, it is making all those
> [ThreadStatic] fields useless.

Then you've got a design issue - it doesn't mean it's a bug.

> This is driving me crazy.
>
> The event MUST be fired on the same thread that created TransactionScope and
> subscribed this event.

Well, it must for your code to work. I can't immediately see anything
in the documentation suggesting that that should happen though.

> But the Microsoft implemented in a way, that the initial thread is stopped
> and a different thread is used to fire the event (WHY???).  After the event
[quoted text clipped - 5 lines]
>
> Since this is not explained in any documentation, I think it is a bug.

Where is the guarantee to that it *will* occur in the same thread? If
there's no guarantee, you're relying on unspecified behaviour, which
you assumed would be the behaviour you wanted.

What would you expect to happen if you'd called BeginCommit from a
thread which wasn't running a message pump? How would you expect it to
marshall back to that thread?

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Cowboy (Gregory A. Beamer) - 21 Mar 2008 17:54 GMT
I was not going to add anything here, as Jon has already provided a long
answer, but it started nagging on me, so I apologize, in advance.

First, let's understand bug and design flaw. Suppose I create a library that
creates a binary array out of a string. As I am working with English only, I
design this to return a single byte per character in the string. You,
working in another language, find that it is not giving you enough fidelity
to reproduce your string on the other end. So you call and say I have a bug.

My library does what I said it would do, so it is not a bug. If my library
turned the word fudge into the binary representation of turds, it would be a
bug, as it is not working as I stated it would work.

It could, however, be a design flaw, as it only works with ASCII values. The
question of whether or not it is a design flaw depends on stated intent. For
example, "creates a binary representation of an ASCII string" would not
indicate a design flaw, while "creates a binary representation of any
string" would.

-----------

Next, I see the statement
> I have cleanup routines which were tied to that specific transactions
> created for that specific thread

So, you have a cleanup dependent not ONLY on the transaction, but on the
particular thread. This means your cleanup is actually work that is part of
the transaction, as it has a very tightly coupled dependency on more than
the work being done, but the actual manner in which it is completed. In
other words, the TransactionScope is not really what you are concerned with,
but the thread created to complete the TransactionScope.

If you ask me, it is a design flaw. It might be Microsoft's design flaw, as
they have not included a way to create a transaction for a transaction and
its cleanup. But, as you have the dependency, I would also argue that you
have a design flaw in your own code, as the TransactionScope is acting
exactly as published.

Let's, however, focus on it being a bug that Microsoft needs to fix. If so,
it will likely take weeks, at minimum, before we see a patch of any sort,
and months before a fully regression tested patch. Can you wait this long
before you fix the problem? If yes, then get on connect and log the bug. If
not, I would find a way to eliminate the thread dependency in your code. At
this point, working code is probably better than being right.

Signature

Gregory A. Beamer
MVP, MCP: +I, SE, SD, DBA

Subscribe to my blog
http://gregorybeamer.spaces.live.com/lists/feed.rss

or just read it:
http://gregorybeamer.spaces.live.com/

*************************************************

| Think outside the box!

*************************************************
>I have posted this issue earlier on
>microsoft.public.dotnet.languages.csharp, but nobody replied to that.
[quoted text clipped - 49 lines]
>
> AM.
Peter Ritchie [C# MVP] - 25 Mar 2008 20:46 GMT
The TransactionCompleted event is raised on the thread on which the
transaction is running.  This is very common for events, if thread affinity
isn't documented then you can't assume it will occur on any particular
thread.  It's your applications requirement that the event handle execute on
a given thread.  It's your application's responsibility to marshal the call
to another thread, if needed.

Given that a Form cannot have it's form data accessed by any other thread,
why are you using the ThreadStatic attribute on fields on a Form class anyway?

Signature

Browse http://connect.microsoft.com/VisualStudio/feedback/ and vote.
http://www.peterRitchie.com/blog/
Microsoft MVP, Visual Developer - Visual C#

> I have posted this issue earlier on
> microsoft.public.dotnet.languages.csharp, but nobody replied to that.
[quoted text clipped - 44 lines]
>
> Since this is not explained in any documentation, I think it is a bug.
Ben Voigt [C++ MVP] - 25 Mar 2008 23:00 GMT
> The TransactionCompleted event is raised on the thread on which the
> transaction is running.  This is very common for events, if thread
[quoted text clipped - 6 lines]
> thread, why are you using the ThreadStatic attribute on fields on a
> Form class anyway?

The data associated with a Form can be accessed from any thread, what makes
you think otherwise?  Only operations that require sending windows messages
to the HWND have thread affinity.
Peter Ritchie [C# MVP] - 26 Mar 2008 01:52 GMT
"Form data" as in controls.  It's actually a combination of windows messages
and the fact that the main (GUI) thread must be STA that cause cross-thread
control access exceptions.

But, the documentation for Control.InvokeRequired details it quite well:
"Controls in Windows Forms are bound to a specific thread and are not thread
safe. Therefore, if you are calling a control's method from a different
thread, you must use one of the control's invoke methods to marshal the call
to the proper thread."

There's certain cases where you don't have to Invoke; but it's difficult to
track down which will and which won't case an exception and usually just
easier to marshal all access to the form's thread.

Signature

Browse http://connect.microsoft.com/VisualStudio/feedback/ and vote.
http://www.peterRitchie.com/blog/
Microsoft MVP, Visual Developer - Visual C#

> > The TransactionCompleted event is raised on the thread on which the
> > transaction is running.  This is very common for events, if thread
[quoted text clipped - 10 lines]
> you think otherwise?  Only operations that require sending windows messages
> to the HWND have thread affinity.
Peter Duniho - 26 Mar 2008 02:19 GMT
> "Form data" as in controls.

It seems to me that "form data" is not naturally inferred to mean simply  
"controls".  My guess is that that's the point of disagreement between you  
and Ben.  I think he rightly took issue with the over-general statement  
about what requires the use of Invoke().

As you know, a Form-derived class can and often will have a variety of  
additional data items added by the programmer in that class, and there's  
no fundamental restriction regarding access to that data.  Likewise your  
own methods you might add to the class.  In fact, if it were otherwise, it  
would be impossible to write code such as MSDN recommends, where the same  
method invokes itself in order to get onto the main thread.  You wouldn't  
be able to call that method in the first place.

It's true that most of the properties and methods in the Form class itself  
must be called from the thread that owns that instance of the Form.  But  
other than that, any data or other members in a Form-derived class are  
under no such restriction.  This includes any data the person writing the  
inheriting class might add, as well as any internal (private) data the  
Form class (and its ancestors) might themselves define (though I have no  
idea what that data might be, I'd be surprised if there isn't at least a  
little internal data not directly related to the unmanaged resources used  
by a Form).

Of course, all of the above applies to any class inheriting Control, not  
just forms.  It's just that this happened to come up in the context of a  
comment specifically about a form.

> [...]
> There's certain cases where you don't have to Invoke; but it's difficult  
> to
> track down which will and which won't case an exception and usually just
> easier to marshal all access to the form's thread.

It's not really that difficult.  The MSDN documentation lists the specific  
members that can be called without Invoke(), and of course anything you  
might add to a Form-derived class, you should be able to determine  
yourself whether it requires the use of Invoke().  In fact, there's no  
fundamental reason why _any_ member added in a derived class would  
_require_ the use of Invoke(), though it can often be the simplest  
technique to deal with synchronization to do so anyway.

Pete
Peter Ritchie [C# MVP] - 26 Mar 2008 02:41 GMT
> > "Form data" as in controls.
>
> It seems to me that "form data" is not naturally inferred to mean simply  
> "controls".  My guess is that that's the point of disagreement between you  
> and Ben.  I think he rightly took issue with the over-general statement  
> about what requires the use of Invoke().

Quite possibly.

<snip>
> It's true that most of the properties and methods in the Form class itself  
> must be called from the thread that owns that instance of the Form.

Yes, and that's why I asked about the OP's use of ThreadStatic.  If many (or
even just some) of the form/control's methods/properties need to be marshaled
to a specific thread, having thread-specific fields seems like a really bad
idea.

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.