Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
321 views
in Technique[技术] by (71.8m points)

c# - why there is no EndInvoke in Cross thread UI component call ?

I have been trying to add some string to some ListBox that i have on my application ( simple winform ) - and i did it in using BeginInboke

 myListBox.BeginInvoke(new Action(delegate()
 {
       myListBox.Items.Add( "some string" )); 
 }));

After i reading those 3 lines again - and i don't understand why in any example of Cross thread UI that i look on google and on MSDN i don't see any call of EndInvoke ? Is there some reason to not call the EndInvoke on this case ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This was an unfortunate naming choice in .NET. The Control.BeginInvoke and Dispatcher.BeginInvoke methods have the same name as a delegate's methods but operate completely different. The chief differences:

  • A delegate's BeginInvoke() method is always type-safe, it has the exact same arguments as the delegate declaration. This is entirely missing from the Control/Dispatcher versions, arguments are passed through a params array of type object[]. The compiler will not tell you when you get an argument wrong, it bombs at runtime

  • A delegate's Invoke() method runs the delegate target on the same thread. Not the case for Control/Dispatcher.Invoke(), they marshal the call to the UI thread

  • An exception that's thrown in a delegate's BeginInvoke() target is captured and does not cause the program to fail. To be re-thrown when you call EndInvoke(). This is not the case at all for Control/Dispatcher.BeginInvoke(), they raise the exception on the UI thread. With no decent way to catch the exception, one of the bigger reasons that Application.UnhandledException exists.

  • Calling a delegate's EndInvoke() method is required, it causes a 10 minutes resource leak if you don't. It is not required for the Control/Dispatcher.BeginInvoke() methods and you never do so in practice.

  • Using Control/Dispatcher.Invoke() is risky, it is quite liable to cause deadlock. Triggered when the UI thread isn't ready to invoke the target and does something unwise like waiting for a thread to complete. Not a problem for a delegate, not in the least because its Invoke() method doesn't use a thread.

  • Calling Control/Dispatcher.BeginInvoke() on the UI thread is a supported scenario. The target still runs on the UI thread, as expected. But later, after the UI thread goes idle again and re-enters the dispatcher loop. This is actually a very useful feature, it helps solve tricky re-entrancy problems. Particularly in event handlers for UI controls that will misbehave when you run code with too many side-effects.

A big list with heavy implementation details. The TLDR version is certainly: "They have nothing in common, not calling EndInvoke is fine and entirely normal".


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...