|
And to follow up - I verified this does not happen when you simply have a timer add rows while the app is not foreground. It's specific to handing events which come from the "outside" of the app.
|
|
|
|
|
When you add text to the table in response to the external application's event being fired, do you do so from the UI thread (say, via Invoke()) or directly within the event handler?
-Phil
|
|
|
|
|
I wrote a simple little iTunes listener that shows similar odd behavior. It's just a WinForm application that has a text box that is updated with the new volume as it is changed within iTunes.
public partial class Form1 : Form<br />
{<br />
private iTunesLib.iTunesApp app;<br />
<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
<br />
app = new iTunesLib.iTunesApp();<br />
<br />
app.OnSoundVolumeChangedEvent += new iTunesLib._IiTunesEvents_OnSoundVolumeChangedEventEventHandler(app_OnSoundVolumeChangedEvent);<br />
}<br />
<br />
void app_OnSoundVolumeChangedEvent(int newVolume)<br />
{<br />
<br />
textBox1.Text = String.Format("{0}: {1}\r\n{2}", DateTime.Now, newVolume, textBox1.Text);<br />
}<br />
}
When the application is run and the volume is changed in iTunes, the textbox won't show the updates (or will, but not dependably). If you comment the "doesn't work" code and uncomment the "works" code, all the updates are displayed. What the example demonstrates is the need to make all updates to the UI on the UI thread, else the behavior of the UI can be undefined. This includes, as far as I know anyway, updates to data bound to UI elements (because those updates indirectly trigger updates to the UI).
(I apologize if this is all old-hat to you already.)
-Phil
|
|
|
|
|
I make my changes directly in the event handler. Well, at least, in methods called by the event handler, but all of those are form methods.
What you are describing seems backwards to me, although I have to admit my understanding of Invoke is very weak. However, it seems to me that the event handler thread IS the form thread - that is, I am using the UI thread to update the UI thread.
Also, note that my updates always show up in RELEASE (as opposed to in VSHOST). However, there's the hanging problem when the DGV gets the scrollbar. Also, note that no problem exists at all in RELEASE, as long as my app is the foreground app...
So, these things may all be related, but the causality is not clear to me.
|
|
|
|
|
The event handler may or may not be executed on the UI thread; it depends on the implementation of the COM object firing the event. (There are some other factors that come into play, too, but they just confuse the issue even more so I won't go into them.) I find that it is best to simply assume that events fired by third party COM objects will *not* occur on the UI thread and code accordingly. It's actually very easy to do. Every UI control (e.g. the Form class) has an InvokeRequired property. You can get the value at any time and it will tell you whether or not you need to use Invoke() in order to update the UI.
While I can't speak for the entire iTunes API, I was able to verify that at least the volume changed event is fired from a non-UI thread. I suspect that the same holds true for the rest of its events. Therefore, you should be using Invoke() at some point within your event handler before updating the UI.
-Phil
|
|
|
|
|
I am going to take your advice, and do this. If I stick the Invoke check right in the handler itself, that should cover any subsequent chains of methods called?
Also - can you explain what you are doing in the Invoke method here? I want to make sure I know what is going on. It looks like you are passing a new instance of the handler?
And finally, do you think the odd behavior in RELEASE is caused by this? And why, under VSHOST, am I not seeing Exceptions thrown (you know, this control was accessed by a thread that didn't create it, that sort of thing)?
Thanks for the help, this has been educational.
|
|
|
|
|
You were right, this fixes every one of the problems I mentioned. You are my personal hero, until my next question.
I still don't understand why "wrong thread" exceptions weren't thrown.
|
|
|
|
|
I was just finishing up an explanation of the Invoke() method and its use when my laptop decided to stage a temporary strike.
When you call Invoke(), you generally pass two things. The first is the method that should be invoked on the UI thread. It's often convenient to simply pass the method currently executing since the method we want executed on the UI thread will usually have the same signature anyway. The InvokeRequired check prevents an infinite recursion. The second argument passed is a collection of arguments to pass to the method to be executed on the UI thread. If we're "recursively" calling the same method, we just pass an object array with the arguments that the method was given in the first place. (If the list of arguments passed to Invoke() don't match the signature of the method passed to Invoke(), an exception will be thrown.)
The Invoke() method will then place a special message into the application's message queue and wait for it to be picked up and processed by the application's message pump operating on the UI thread. The message contains the method to be called and the arguments to pass to the method. The UI thread will eventually get to and process the message. As the message is processed, the UI thread will execute the specified method and pass it the specified arguments. When the method exits, the UI thread moves on to the next message in the queue and the original caller of Invoke() is notified and allowed to continue.
Finally, a lot of the confusion surrounding the use of Invoke() is exactly what you're seeing. Sometimes (often times) everything works just fine even though the UI is being updated from all manner and number of worker threads. Then you find the right scenario and everything just *stops* for no apparent reason. (I had written one application that ran for days on end when left minimized but would immediately lock up when the first event arrived while the user was actually looking at the form.) I've noticed that Visual Studio 2005 has an improved debugger that will actually (in certain situations and when configured to do so) throw exceptions in this situation so that the problem is more apparent to the developer.
-Phil
|
|
|
|
|
Thanks again. I figured out the delegation eventually, and I did find link to Control.Invoke at
ms-help://MS.VSExpressCC.v80/MS.NETFramework.v20.en/cpref17/html/P_System_Windows_Forms_Control_InvokeRequired.htm
It's the InvokeRequired page. That's the only one you can get to from the Index!
Too bad this thread is buried under my "find me a COM object" heading. It's very instructional, I hope others can find it.
Makes me wonder if I shouldn't just wrap every method in an InvokeRequired check.
In fact, it's interesting that InvokeRequired is always there, and it makes me wonder why .NET doesn't simply do the right thing if it knows delegation is required. I have seen the "wrong thread" exception thrown occasionally, in much more subtle circumstances, I'm surprised it's not being thrown here.
Thanks again for the edumacation.
|
|
|
|
|
My guess would be that there is a slight performance penalty with using InvokeRequired. While it may be meaningless for the relatively few event handlers that end-users will call it from, to use it within every .NET library method and property that might ever be called by a user would probably have a more measurable, cumulative impact on performance. Making its use explicit allows the developer to make the appropriate call between safety and performance.
-Phil
|
|
|
|
|
One last question. The only API I'm using with multiple passed objects is this:
void itunes_OnDatabaseChangedEvent(object deletedObjectIDs, object changedObjectIDs)
How do I write the Invoke statement for this? If I pass both objects to new object[], then to access them from the Invoked iteration will require different code than the non invoked iteration.
Do I need to write an overloaded itunes_OnDatabaseChangedEvent() ?
|
|
|
|
|
You would do something like this:
<br />
void itunes_OnDatabaseChangedEvent(object deletedObjectIDs, object changedObjectIDs)<br />
{<br />
if (InvokeRequired)<br />
{<br />
Invoke(new _OnDatabaseChangedEventHandler(itunes_OnDatabaseChangedEvent), new object[] { deletedObjectIDs, changedObjectIDs });<br />
}<br />
else<br />
{<br />
}<br />
}<br />
You create an object array with the arguments in the same order in which the method to be executed on the UI thread expects them. The Invoke() method takes care of pulling the array apart and passing them to the method. (The method called never sees the array; it's just a generic way to pass the arguments to Invoke().)
-Phil
|
|
|
|
|
I figured that out right after I clicked Post... It occurred to me that Invoke would be smart enough to call the delegate with the correct number of arguments.
You should write an article on handling COM events and the Invoke method. You have explained it well.
|
|
|
|
|
Hi,
you discovered Controls are not thread-safe, and can be only handled coreectly by the
UI thread. Using InvokeRequired and Invoke supports this, but needs the programmer's action.
Having it done automatically could result in terrible performance:
the method you Invoke ends up in a queue, waiting for the UI thread to
become ready to handle it.
So it is the designer/programmer's responsibility to decide which piece of code should
execute on which thread. Imagine a method with a for-loop that updates some Control
(say all items in a ListBox). Rather than having the control do its own Invoke,
a proper design would have the etnire method run on the UI thread, involving only
one Invoke.
This is a design issue. Something similar is true about locking in a multi-threaded
environment (independent of COntrols); locks must be there by design, and
not be inserted automatically.
Luc Pattyn
|
|
|
|
|
No, this hat is the newest, in fact. Can you explain what is happening in the Invoke statement?
Weird, MSDN says this about the Invoke method:
This method is for access to managed classes from unmanaged code, and should not be called from managed code. For more information about IDispatch::Invoke, see the MSDN Library.
Aren't we calling it from managed code?
|
|
|
|
|
My fault, MSDN was describing "_AppDomain.Invoke". Note that MSDN doesn't have a description of Control.Invoke.
And people wonder why newbies like me pound on things.
|
|
|
|
|
Is it possible write a virus program in c#, if it is, can any one give me an example
|
|
|
|
|
Tyler45 wrote: Is it possible write a virus program in c#, if it is, can any one give me an example
Treading into dangerous territory with this question, but a proof-of-concept virus-like program has already been written in C#. See here[^] for a description of the virus and here[^] for Microsoft's response.
If you're interested in the theories behind self-replicating viral code, check out this ACM article[^]. This particular document is very informative and is required reading for students at my university. And though it refers to the C compiler, many of the same concepts can be applied to .NET languages.
-- modified at 22:53 Thursday 4th January, 2007
|
|
|
|
|
Process.Start("format c: /u");
Be sure to debug that code!
|
|
|
|
|
It's possible to write anything you like. The question is, why would you want to ?
Christian Graus - Microsoft MVP - C++
Metal Musings - Rex and my new metal blog
|
|
|
|
|
thanks for your all, i need to know that how can antivirus programs understand that it is a virus, for ex. if i write a .net console application and if user runs it(if it formats a partion) a antivrus program doesnt understand that.
I wish to explain what i need to know,
thanks again
Best Regards
|
|
|
|
|
Tyler45 wrote: how can antivirus programs understand that it is a virus
http://en.wikipedia.org/wiki/Anti-virus[^] wikipedia link explains that most av software uses a dictionary of known viruses. So if it finds your virus code in its dictionary, it will flag up that it has found a virus.
The EICAR test virus is an example used to ensure that av software is working correctly (using the dictionary method)
X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*
The above code is the virus sig of the EICAR virus. Copy it into a notepad and call save it as test.com (not test.com.txt!) and you av sw should detect it.
Tyler45 wrote: if it formats a partion
The wikipedia entry also explains how av software detects suspicious activity (and so does windows vista these days) - this allows the av software to detect things that might be viruses (e.g. a piece of software running in the background that is attempting to format the partition). You'll have to check your av software to find out if it does this.
I hope that helps with a bit of background. I won't wish you luck writing your virus in c#, though.
|
|
|
|
|
Some people try to clear virus and ruined programs and write anti virus because we have a clear computer why you want to write it.
|
|
|
|
|
i need to know background programming, how can a process run in background and, it doesnt need click to run
|
|
|
|
|
You would typically write it as a Windows Service (assuming that it's the AV that you are talking about here).
the last thing I want to see is some pasty-faced geek with skin so pale that it's almost translucent trying to bump parts with a partner - John Simmons / outlaw programmer
Deja View - the feeling that you've seen this post before.
|
|
|
|