|
If you are running an app on the users machine then sure, you can download a file and put it on the users machine. You can run it too once it is down.
You can use the WebRequest class to get files over HTTP. You can then use a stream writer to write it to disk.
regards,
Paul Watson
South Africa
The Code Project
South-East Asia Disaster: How you can help
Pope Pius II said
"The only prescription is more cowbell. "
|
|
|
|
|
I was wondering how can I have my application setup and recieve global shortcuts. Basically, I want my program to run in the background and recieve the shortcut no matter what application has focus (kind of like WinAmp does).
Where can I find articles/example code on this? Or where should I start to look in the SDK?
Thanks for all your help!!
|
|
|
|
|
I believe you'll have to use some Windows Hooks for this. I read an article on it once, I just have to find it again...
Here it is:
http://msdn.microsoft.com/msdnmag/issues/02/10/CuttingEdge/
Here's a good one about global hooks from CP.
There are two types of windows hooks: local hooks, which catch messages coming in for one particular thread, and global hooks, which catch messages for all threads on the entire system.
This space for rent!
My Blog
|
|
|
|
|
Thanks alot for the info!
|
|
|
|
|
I have a main thread that executes many threads of a specified class. All are the same class.
After creating the threads and executing then at the same time, I need a way in which I can monitor all the threads.
If one of the threads meets a certain condition I need to be able to contact each thead that was started and call the join method on it.
Its model is like so:
Controller A starts
Creates x number of threads with class A
one of the class's (A) will signal its finished and at that point the controller will call join on every thread started.
I need a way so make sure all threads created are shut down cleanly.
Any Ideas,
Nick
I'm not an expert yet, but I play one at work. Yeah and here too.
|
|
|
|
|
I'm definitely no expert, but here's my idea:
Class A should expose a ManualResetEvent via a public property. When the class is constructed, create an instance of the ManualResetEvent class and set it's initial state to non-signalled (by passing in false as a parameter to the constructor).
Now every object you create of class A has it's own ManualResetEvent, which can be used to signal when that class has completed it's work by calling ManualResetEvent.Set() .
When you create an object of class A, store it's ManualResetEvent in an array of type WaitHandle . This could be the tricky part - if you create the object before the thread starts, you should have no problems. However, if the thread creates the object, this method will not work (as you can't get a hold of the object).
The controller will then create all of your threads and keep them in a collection for access later so that you can call Join on them.
Now, perform any processing you need to do for the Controller and when you're ready to wait for your signal from one of the classes, simply call WaitHandle.WaitAny(WaitHandle[]) , and pass in your collection of WaitHandle s as the parameter.
WaitHandle.WaitAny() will immediately return when any of the WaitHandles becomes signalled. Once this occurs, loop through your collection of threads and call Thread.Join() on each of them.
I hope that makes sense. It may not be the best way to do it, but that's what I would do personally (like I said, I'm not expert ).
This space for rent!
My Blog
|
|
|
|
|
reply ?
Its a very good idea.
So would I have class A inherit the Thread class and how would I implement the WaitHandle?
How does the wait handle get back to the thread to Join the main thread?
I have it woring, but a little confused on useing WaitHandles which I really want to do.
Thanks,
Nick
I'm not an expert yet, but I play one at work. Yeah and here too.
|
|
|
|
|
Hi Nick.
First I suggest you read the documentation on the System.Threading.ManualResetEvent class (here). In a nutshell:
The ManualResetEvent provides a way for you to notify other threads when you have completed a task.
All Class A needs to do is provide it's own ManualResetEvent that the controller can access and store away. Once all of the threads are created the controller can then call System.Threading.WaitHandle.WaitAny() , passing in an array of the ManualResetEvent s (one per class object you created) that it kept. As ManualResetEvent derives from WaitHandle , this is perfectly valid.
The call to WaitHandle.WaitAny() will then block the controlling thread until one of the ManualResetEvents you supplied is set to signalled (ie, indicating that a class on another thread finished processing - you don't know which one, but you know that at least one of them has finished).
Once this occurs, the controller thread will then be allowed to continue, regardless of whether the other threads have finished processing or not (that is possible because you called WaitAny , not WaitAll ).
Now, you asked how the WaitHandle notifies the other threads that it has been signalled. That one I don't know, sorry. I might do some research into it, however.
If you need any more help, let me know.
Good luck.
This space for rent!
My Blog
|
|
|
|
|
Greatings !!! I have a simple (I think) problem.
I need a thread that executes some part of a code and
during that time i want to suspent or pause the main application thread.
This way the application do not appear (Not Responding) or is the same? Do you have another solution?
How can i do this?
Sorry for my English !!!
thanks.
Bruno Conde.
|
|
|
|
|
Arg, please don't abuse threading like this.
If you want to execute something in another thread yet suspend the main thread why bother seperating the two things into two threads?? You are not gaining anything using threading like this. Just do all of the work in the single main thread.
|
|
|
|
|
In most cases I would totally agree with you.
There are cases, however, when you may want to execute something in another thread and eventually have your application block until it's finished. This is quite possible with the asynchronous pattern, when you first call Begin* , do something else, then block on End* . I would add, however, that's more common to use an AsyncCallback so that you don't have to block, but you could.
An example might be downloading a file via HttpWebRequest.BeginGetResponse . You could update the UI and then call HttpWebREquest.EndGetResponse to block until the HttpWebResponse is returned.
I'm not disagreeing that - if the original poster needs no functionality like what I descrbied - it is an abuse of threads. There may be a purpose, however (of which we would know since the original post mentioned nothing of this sort).
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Agreed, there are cases where you really need to use multi-threaded behavior and the example is a perfect example (begin/end process pipelines are classic MT fodder). Without more information however it sounds like the described problem can be fixed simply by avoiding MT all together.
Sometimes the vague nature of the questions makes me suspicious which is why I asked the question. If they can come up with the answer on why their app relies on MT behavior that requires going against MT behavior then we can actually go forward and get a better solution than vaguely throwing code around.
|
|
|
|
|
And I completely agree with you. I added a response to yours mainly for the original poster's benefit, since he/she might have a valid reason that falls under the scenario I mentioned.
Turns out, though, that he/she is using Control.Invoke , apparently thinking that it will invoke the method on a different thread. Further proof that reading documentation is always beneficial.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
There's a couple ways of doing that. You can use Thread.Join in your main application thread. You would do something like this:
Thread t = new Thread(new ThreadStart(SomeMethod));
t.Start();
t.Join() Now your main application thread (or in whichever thread you called Join will block until the thread terminates.
Another way is through asynchronous processing and gives you added functionality, like callbacks. Many objects define asynchronous methods already (the Begin* and End* method pairs), but you execute any method (including property getters and setters, which are just methods) asynchronously like so:
using System;
using System.Threading;
delegate void VoidCallback();
class Test
{
static void Main()
{
Test t = new Test();
VoidCallback callback = new VoidCallback(t.DoSomething);
IAsyncResult result = callback.BeginInvoke(null, null);
Thread.Sleep(1000);
Console.WriteLine("Still in Main() on main thread");
callback.EndInvoke(result);
Console.WriteLine("Done");
}
void DoSomething()
{
Console.WriteLine("Waiting for 3 seconds in new thread...");
Thread.Sleep(3000);
}
} While this is possible, however, an application should never appear hung (which is what you're doing). If you don't want the user to be able to interact with the application while still allowing the control thread (the thread on which the controls were created) to paint the controls (so the application doesn't appear hung), then simply set the wait cursor by doing Cursor.Current = Cursors.WaitCursor; . You can do this for a particular control (including the form, which extends Control ) by setting Control.Cursor or for the entire application by using Cursor.Current . Be sure to restore the original cursor, however, or the user won't be able to interact (i.e., give intput) with your application.
For example:
Cursor orig = Cursor.Current;
try
{
Cursor.Current = Cursors.WaitCursor;
}
finall
{
Cursor.Current = orig;
}
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
When I set Cursor.Current to the WaitCursor then start a thread to do a long process the Cursor doesn't remain as the WaitCursor it almost immediately changes back to the default cursor.
My long process fires an event to say it has started and I handle that on the GUI thread (yes I am using invoke required and delegates) - this sets the Cursor.Current to the WaitCursor then when the long process has completed it fires another event which is handled on the GUI thread which sets the Cursor.Current to the default cursor. I would like the Cursor to remain as the WaitCursor until the long process has completed but no amount of jiggery pokery seems to enable me to do that - I have had to resort to disabling huge amounts of the GUI so the user can't mess up - a WaitCursor would be nice but it just isn't happening.
I know the following is in VB but I haven't had much joy on the VB forum.
The long running process fires off an event every 1000 records or so which is handled on the GU thread thus:
Private Delegate Sub xxxDelegate(ByVal sender As Object, ByVal e As xxxEventArgs)<br />
<br />
Private Sub xxx(ByVal sender As Object, ByVal e As xxxEventArgs) Handles LongProcess.xxx<br />
<br />
If button.InvokeRequired = False Then<br />
Console.WriteLine("A - " & Cursor.Current.ToString())<br />
...<br />
Else<br />
Console.WriteLine("B - " & Cursor.Current.ToString())<br />
Dim del As New xxxDelegate(AddressOf xxx)<br />
Me.BeginInvoke(del, New Object() {sender, e})<br />
End If<br />
End Sub
When run the following is written to the console:
B - [Cursor: WaitCursor]
A - [Cursor: Default]
B - [Cursor: WaitCursor]
A - [Cursor: Default]
B - [Cursor: WaitCursor]
A - [Cursor: Default]
|
|
|
|
|
You wouldn't be calling Application.DoEvents would you? If not, you might run your application through a profiler (available from MSDN[^] even) to see if it's getting called automatically be something else.
From the .NET Framework SDK for the Cursor.Current property:Note If you call Application.DoEvents before resetting the Current property back to the Cursors.Default cursor, the application will resume listening for mouse events and will resume displaying the appropriate Cursor for each control in the application.
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
The app does call DoEvents but not anywhere touched by the long process - I usually call DoEvents after closing down a Dialog. I have run it under a profiler and DoEvents doesn't come into it.
I am kicking off the long process using BeginInvoke - if that helps.
|
|
|
|
|
Where do you actually set Cursor.Current ? Can you show me the rest of the code minus your application-specific implementation?
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
Hope this makes sense
Private Delegate Sub RunCrosstabDelegate(ByVal rowVar As String, ByVal colVar As String, ByVal thirdVar As String)
Private Sub RunCrosstab()
Dim crosstab As New RunCrosstabDelegate(AddressOf _Counter.RunCrossTab)
crosstab.BeginInvoke(LkCrossTab1.RowVariable, LkCrossTab1.ColVariable, LkCrossTab1.ThirdVariable, Nothing, Nothing)
End Sub
Private Sub _Counter_CrossTabStart(ByVal sender As Object, ByVal e As EventArgs) Handles _Counter.CrossTabStart
If LkCrossTab1.InvokeRequired = False Then
Cursor.Current = System.Windows.Forms.Cursors.WaitCursor
Else
Dim del As New CrossTabStartDelegate(AddressOf _Counter_CrossTabStart)
Me.BeginInvoke(del, New Object() {sender, e})
End If
End Sub
Private Delegate Sub CrossTabFinishedDelegate(ByVal sender As Object, ByVal e As EventArgs)
Private Sub _Counter_CrossTabFinished(ByVal sender As Object, ByVal e As EventArgs) Handles _Counter.CrossTabFinished
If LkCrossTab1.InvokeRequired = False Then
Cursor.Current = System.Windows.Forms.Cursors.Default
'
Else
Dim del As New CrossTabFinishedDelegate(AddressOf _Counter_CrossTabFinished)
Me.BeginInvoke(del, New Object() {sender, e})
End If
End Sub
|
|
|
|
|
In your previous post you made it sounds like there was also an event that fired intermitently while the long process was running. Is that true? If so, do you set the wait cursor at all in that loop?
When you profiled your application, no Application.DoEvents ran at all while processing the crosstab? From the code above I don't see a problem. It would seem another thread is either setting the cursor or dispatching queued messages (in the application pump). Since you're running asynchronously, this is entirely possible and most likely the case.
Try running this synchronously and you should find that it works because the application (or dialog) message pump is run (which Application.DoEvents forces). If that does work, I'm really not sure what to do to work around it, since this is expected behavior.
One thing you could try is setting a Control 's Cursor property instead of the application's. Hopefully that will "stick".
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
DoEvents isn't called at all during the processing. The WaitCursor just won't stick - I have tried setting the cursor on every single control to the WaitCursor - which kind of works although it doesn't stop mouseinput - the user can still click on things, drag stuff around, press buttons etc. So the WaitCursor doesn't seem to do much - is that what is supposed to happen? Is there a way to disable mouseinput without disabling every single control?
|
|
|
|
|
What are you using to profile the execution of your application? On other thing you might try is to override OnCursorChanged and set a breakpoint to see if anything else is setting it. Note that this event handler is not called if a native call changes it.
You could set Form.KeyPreview on the container form and disable keys effectively, but to disable mouse events for all child controls you'll need override WndProc on the form and handle the WM_PARENTNOTIFY (0x0210) message, where the low order (second half) of the Message.LParam is set to WM_LBUTTONDOWN (0x0201) or WM_RBUTTONDOWN (0x0204), and conditionally handle the message (allow it to be processed by calling base.WndProc(ref Message) ). Your code must be fully trusted to override WndProc .
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|
|
use <threadobject>.Join()
this way this thread (whose instance is mentioned above) would wait for all child threads to "die" first before proceeding.
|
|
|
|
|
Thanks for the tip. If after i create the thread t and then do t.Join() the application don't stay "Not Responding" but it stays stopped until the thread t stopps. I think that the application stay's in "Not Responding" because in ApplicationTick1() i refer a recursive method. This method takes a while to do it's job and in that while the application stays "Not Responding". Here is a sample of the code in ApplicationTick1:
// preenche a arvore
MyDelegate d = new MyDelegate(LDAPLibrary.Class1.FillTreeView);
this.Invoke(d,new object[] {conn,tv.Nodes,p2,true});
|
|
|
|
|
That won't start a new thread. Control.Invoke actually executes the method on the thread on which the control was created. That's useful when you're doing something in a different thread and need to update the UI. As I said in my reply, you must always update the UI on the thread on which the control was created. That's why the Control class implements ISynchronizeInvoke .
This posting is provided "AS IS" with no warranties, and confers no rights.
Software Design Engineer
Developer Division Sustained Engineering
Microsoft
[My Articles] [My Blog]
|
|
|
|