I make a thread which do some work and run shutdown.exe to shutdown the pc.
Worker work = new Worker();
Thread thread = new Thread(new ThreadStart(work.DoWork));
thread.Start();
and the method DoWork()
public void DoWork()
{
/* Do some thing */
// This will shutdown the PC
ProcessStartInfo startInfo = new ProcessStartInfo(Environment.GetFolderPath(System.Environment.SpecialFolder.System) + #"\shutdown.exe", "-s -t 5");
Process.Start(startInfo);
}
If i call method work.DoWork() in main thread, the PC'll shutdown.
But if i put it in thread using thread.Start(), the pc won't shutdown.
Edit:
Found my mistake. I create a thread-safe call method to read the checkbox which always return false
delegate bool GetcbShutdownCheckedValueCallback();
public bool GetcbShutdownCheckedValue()
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.lblCraftRemain.InvokeRequired)
{
GetcbShutdownCheckedValueCallback d = new GetcbShutdownCheckedValueCallback(GetcbShutdownCheckedValue);
this.Invoke(d);
}
else
{
return cbShutdown.Checked;
}
return false;
}
I call the method to check if the check box is checked then shutdown. So actually the code isn't executed.
If you want to shut the computer down it's better to call Win32's ExitWindows function rather than running the shutdown.exe program.
There's MSDN documentation here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa376867%28v=vs.85%29.aspx
And the C# P/Invoke signature here: http://www.pinvoke.net/default.aspx/user32.exitwindowsex
Related
FURTHER EDIT
the following is not production code - I'm just playing around with a couple of classes trying to figure out how I run processes within threads - or even if that is viable. I've read various definitions on MSDN but am a newbie to threads and processes so any further definitive references to articles would be appreciated
this is fine...
class Program {
static void Main(string[] args) {
Notepad np = new Notepad();
Thread th = new Thread(new ThreadStart(np.startNPprocess));
th.Start();
Console.WriteLine("press [enter] to exit");
Console.ReadLine();
}
}
public class Notepad {
public void startNPprocess() {
Process pr = new Process();
ProcessStartInfo prs = new ProcessStartInfo();
prs.FileName = #"notepad.exe";
pr.StartInfo = prs;
pr.Start();
}
}
this isn't...
class Program {
static void Main(string[] args) {
Process pr = new Process();
ProcessStartInfo prs = new ProcessStartInfo();
prs.FileName = #"notepad.exe";
pr.StartInfo = prs;
ThreadStart ths = new ThreadStart(pr.Start);
Thread th = new Thread(ths);
th.Start();
Console.WriteLine("press [enter] to exit");
Console.ReadLine();
}
}
Why does the second not do the same as the first? In the second script I'm trying to pass Process.Start using the Threadstart delegate ...I thought this would be ok as its a void method?
Is the first script the only option or can I change the second slightly so that it effectively does the same job as the first i.e start an instance of Notepad in a specified thread?
EDIT
Some background as to why I'm playing around with this code: ultimately I need to build an application which will be running several Excel processes simultaneously. These processes can be troublesome when VBA errors as it results in a dialogbox. So I thought if each process was running in a thread then if a particular thread has been running for too long then I could kill the thread. I'm a newbie to Threads/Processes so basically playing around with possibilities at the moment.
A ThreadStart expects a delegate that returns void. Process.Start returns bool, so is not a compatible signature. You can swallow the return value in by using a lambda that gives you a delegate of the correct return type (i.e. void) as follows:
Process pr = new Process();
ProcessStartInfo prs = new ProcessStartInfo();
prs.FileName = #"notepad.exe";
pr.StartInfo = prs;
ThreadStart ths = new ThreadStart(() => pr.Start());
Thread th = new Thread(ths);
th.Start();
...but it's probably advisable to check the return value:
ThreadStart ths = new ThreadStart(() => {
bool ret = pr.Start();
//is ret what you expect it to be....
});
Of course, a process starts in a new process (a completely separate bunch of threads), so starting it on a thread is completely pointless.
you can make changes like
ThreadStart ths = new ThreadStart(delegate() { pr.Start(); });
Just start the process normally using this code:
Process.Start("notepad.exe");
There is no point and no benefits in creating a thread to run a new process. It's like running a batch file that executes "cmd.exe" when you can directly execute "cmd.exe"... you are just doing more than what's necessary for nothing. Don't reinvent the wheel and play easy :P
Not answering directly the OP, but as this thread helped me track the right direction, I do want to answer this:
"starting it on a thread is completely pointless"
I have a .Net server that uses NodeJS as its TCP socket manager. I wanted the NodeJS to write to the same output as the .Net server and they both run in parallel. So opening in a new thread allowed me to use
processNodeJS.BeginErrorReadLine()
processNodeJS.BeginOutputReadLine()
processNodeJS.WaitForExit()
while not blocking the main thread of the .Net server.
I hope it makes sense to someone and if you have a better way to implement what I've just described, I'll be more than happy to hear.
You can start the process in another thread by using the start keyword like below this cod:
Process.Start("start notepad.exe");
in this way, your GUI program doesn't freeze when you run the notepad.
I've written a program in C# that runs as a Windows Service. The application starts up and runs fine, but the OnStop function doesn't get called when I use the Management Console to stop the service.
The OnStart method starts a background thread for the main program, and that background thread starts another thread and a ThreadPool to do work for it.
OnStop I set a boolean flag that all the other threads check in order to see if they should stop processing. The threads should all then finish, and the program should end.
Here's the code for my OnStart
protected override void OnStart(string[] args)
{
base.OnStart(args);
mainProgram.IsBackground = true;
mainProgram.Start();
}
That code works. Below is the code for OnStop, which as far as I can tell doesn't ever get called.
protected override void OnStop()
{
Log.LogMessage("Caught shutdown signal from the OS", "debug");
base.OnStop();
shutdown = true;
mainProgram.Join(15000);
if (mainProgram.IsAlive) mainProgram.Abort();
}
That log message never gets written to the log file.
Any help would be appreciated. I don't even know where to start looking. Thanks.
EDIT
I solved the problem that was locking the background thread. I also commented out that logging statement, so I know the log statement isn't causing the problem.
I added a ManualResetEvent in addition to the boolean flag. The OnStop now looks like this:
protected override void OnStop()
{
System.Diagnostics.Debugger.Break();
//Log.LogMessage("Caught shutdown signal from the OS", "debug");
base.OnStop();
shutdown = true;
ShutdownX.Set(); //this is the ManualResetEvent
mainProgram.Join(15000);
if (mainProgram.IsAlive) mainProgram.Abort();
}
The place this should stop the code is here in the mainProgram.RunAgent() function (which is its own thread)
while (!shutdown)
{
SqlCommand DbCommand = dbConnection.CreateCommand();
DbCommand.CommandText = "SELECT id, SourceID, CastingSN, Result FROM db_owner.queue";
SqlDataReader DbReader = null;
try
{
DbReader = DbCommand.ExecuteReader();
while (DbReader.Read() && !shutdown)
{
long SourceID = DbReader.GetInt64(1);
string CastingSN = DbReader.GetString(2);
bool Result = DbReader.GetBoolean(3);
WaitCallback callback = new WaitCallback(oComm.RunAgent);
CommunicatorState commstate = new CommunicatorState(CastingSN, Result, SourceID);
ThreadPool.QueueUserWorkItem(callback, commstate);
callback = null;
commstate = null;
}
//Console.WriteLine("Finished Queueing Threads");
}
catch (SqlException Ex)
{
Log.LogMessage("There was an error with a query run on the FlexNet Database.", "error");
Log.LogMessage(">> " + Ex.Message, "error");
}
finally
{
if (DbReader != null) DbReader.Dispose();
DbCommand.Dispose();
}
ManualResetEvent[] handles = new ManualResetEvent[2] { eventX, ShutdownX };
WaitHandle.WaitAny(handles);
//eventX.WaitOne(Timeout.Infinite, true);
}
I think this should read from the database, queue up all the threads it finds, then wait for either all the threads to finish processing (the eventX reset event) or the ShutdownX Event.
Once the ShutdownX event is triggered, the outer loop shouldn't continue because the shutdown bool is true, then the thread closes it's SQL connections and should terminate. None of this happens. Any ideas?
You are using ThreadPool. OnStop is reportedly never called until all tasks in the thread pool complete. See also here and here. However, I am leaning towards this not being the main or only cause as some people seem to be using it with success.
It seems to me that your question currently says that OnStop never gets called but that you have seen the log message that it emits. So I assume that OnStop does get called but that some of the threads do not notice that.
Please wrap all code that gets or sets shutdown in a lock statement, using a single global object. This is not for atomicity or mutual exclusion. This is to ensure proper memory barriers on a multiprocessor system.
I am looking for a way to call a method on a new thread (using C#).
For instance, I would like to call SecondFoo() on a new thread. However, I would then like to have the thread terminated when SecondFoo() finishes.
I have seen several examples of threading in C#, but none that apply to this specific scenario where I need the spawned thread to terminate itself. Is this possible?
How can I force the spawned thread running Secondfoo() to terminate upon completion?
Has anyone come across any examples of this?
If you actually start a new thread, that thread will terminate when the method finishes:
Thread thread = new Thread(SecondFoo);
thread.Start();
Now SecondFoo will be called in the new thread, and the thread will terminate when it completes.
Did you actually mean that you wanted the thread to terminate when the method in the calling thread completes?
EDIT: Note that starting a thread is a reasonably expensive operation. Do you definitely need a brand new thread rather than using a threadpool thread? Consider using ThreadPool.QueueUserWorkItem or (preferrably, if you're using .NET 4) TaskFactory.StartNew.
Does it really have to be a thread, or can it be a task too?
if so, the easiest way is:
Task.Factory.StartNew(() => SecondFoo());
Once a thread is started, it is not necessary to retain a reference to the Thread object. The thread continues to execute until the thread procedure ends.
new Thread(new ThreadStart(SecondFoo)).Start();
Asynchronous version:
private async Task DoAsync()
{
await Task.Run(async () =>
{
//Do something awaitable here
});
}
Unless you have a special situation that requires a non thread-pool thread, just use a thread pool thread like this:
Action secondFooAsync = new Action(SecondFoo);
secondFooAsync.BeginInvoke(new AsyncCallback(result =>
{
(result.AsyncState as Action).EndInvoke(result);
}), secondFooAsync);
Gaurantees that EndInvoke is called to take care of the clean up for you.
As far as I understand you need mean terminate as Thread.Abort() right? In this case, you can just exit the Foo(). Or you can use Process to catch the thread.
Thread myThread = new Thread(DoWork);
myThread.Abort();
myThread.Start();
Process example:
using System;
using System.Diagnostics;
using System.ComponentModel;
using System.Threading;
using Microsoft.VisualBasic;
class PrintProcessClass
{
private Process myProcess = new Process();
private int elapsedTime;
private bool eventHandled;
// Print a file with any known extension.
public void PrintDoc(string fileName)
{
elapsedTime = 0;
eventHandled = false;
try
{
// Start a process to print a file and raise an event when done.
myProcess.StartInfo.FileName = fileName;
myProcess.StartInfo.Verb = "Print";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.EnableRaisingEvents = true;
myProcess.Exited += new EventHandler(myProcess_Exited);
myProcess.Start();
}
catch (Exception ex)
{
Console.WriteLine("An error occurred trying to print \"{0}\":" + "\n" + ex.Message, fileName);
return;
}
// Wait for Exited event, but not more than 30 seconds.
const int SLEEP_AMOUNT = 100;
while (!eventHandled)
{
elapsedTime += SLEEP_AMOUNT;
if (elapsedTime > 30000)
{
break;
}
Thread.Sleep(SLEEP_AMOUNT);
}
}
// Handle Exited event and display process information.
private void myProcess_Exited(object sender, System.EventArgs e)
{
eventHandled = true;
Console.WriteLine("Exit time: {0}\r\n" +
"Exit code: {1}\r\nElapsed time: {2}", myProcess.ExitTime, myProcess.ExitCode, elapsedTime);
}
public static void Main(string[] args)
{
// Verify that an argument has been entered.
if (args.Length <= 0)
{
Console.WriteLine("Enter a file name.");
return;
}
// Create the process and print the document.
PrintProcessClass myPrintProcess = new PrintProcessClass();
myPrintProcess.PrintDoc(args[0]);
}
}
I have a long running task in a thread. I
Thread a = new Thread(new ThreadStart()({ delegate()
{
Catalog.Generate(); //long running task
}));
a.Start();
Thread b = new Thread(new ThreadStart()({ delegate()
{
if( File.Exists(stopFile) )
{
a.Abort();
}
}));
b.Start();
This stops Thread A when the stop file is created BUT the catalog.generate method still keeps running? How do I end it?
The problem is your thread b starts working and does the check and immediately exits.
You have to add some sort of loop for the thread b to keep running (this is example code not best practice):
Thread b = new Thread(new ThreadStart()({ delegate()
{
int t=0;
while(i<100)
{
if( File.Exists(stopFile) )
{
a.Abort();
}
else
{
i++;
Thread.Sleep(500);
}
}
}));
"Raises a ThreadAbortException in the thread on which it is invoked, to begin the process of terminating the thread. Calling this method usually terminates the thread."
The abort method sends an indicator that the thread should close. It is dependent on the thread processing as to how it handles this, and when it responds. I would suggest that the Catalog.Generate is probably refusing to respond.
I am new to the thread model in .NET. What would you use to:
Start a process that handles a file (process.StartInfo.FileName = fileName;).
Wait for the user to close the process OR abandon the thread after some time.
If the user closed the process, delete the file.
Starting the process and waiting should be done on a different thread than the main thread, because this operation should not affect the application.
Example:
My application produces an html report. The user can right click somewhere and say "View Report" - now I retrieve the report contents in a temporary file and launch the process that handles html files i.e. the default browser. The problem is that I cannot cleanup, i.e. delete the temp file.
"and waiting must be async" - I'm not trying to be funny, but isn't that a contradiction in terms? However, since you are starting a Process, the Exited event may help:
ProcessStartInfo startInfo = null;
Process process = Process.Start(startInfo);
process.EnableRaisingEvents = true;
process.Exited += delegate {/* clean up*/};
If you want to actually wait (timeout etc), then:
if(process.WaitForExit(timeout)) {
// user exited
} else {
// timeout (perhaps process.Kill();)
}
For waiting async, perhaps just use a different thread?
ThreadPool.QueueUserWorkItem(delegate {
Process process = Process.Start(startInfo);
if(process.WaitForExit(timeout)) {
// user exited
} else {
// timeout
}
});
Adding an advanced alternative to this old question. If you want to wait for a process to exit without blocking any thread and still support timeouts, try the following:
public static Task<bool> WaitForExitAsync(this Process process, TimeSpan timeout)
{
ManualResetEvent processWaitObject = new ManualResetEvent(false);
processWaitObject.SafeWaitHandle = new SafeWaitHandle(process.Handle, false);
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
RegisteredWaitHandle registeredProcessWaitHandle = null;
registeredProcessWaitHandle = ThreadPool.RegisterWaitForSingleObject(
processWaitObject,
delegate(object state, bool timedOut)
{
if (!timedOut)
{
registeredProcessWaitHandle.Unregister(null);
}
processWaitObject.Dispose();
tcs.SetResult(!timedOut);
},
null /* state */,
timeout,
true /* executeOnlyOnce */);
return tcs.Task;
}
Again, the advantage to this approach compared to the accepted answer is that you're not blocking any threads, which reduces the overhead of your app.
Try the following code.
public void KickOffProcess(string filePath) {
var proc = Process.Start(filePath);
ThreadPool.QueueUserWorkItem(new WaitCallBack(WaitForProc), proc);
}
private void WaitForProc(object obj) {
var proc = (Process)obj;
proc.WaitForExit();
// Do the file deletion here
}
The .NET 5 introduced the new API Process.WaitForExitAsync, that allows to wait asynchronously for the completion of a process. It offers the same functionality with the existing Process.WaitForExit, with the only difference being that the waiting is asynchronous, so it does not block the calling thread.
Usage example:
private async void button1_Click(object sender, EventArgs e)
{
string filePath = Path.Combine
(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
Guid.NewGuid().ToString() + ".txt"
);
File.WriteAllText(filePath, "Hello World!");
try
{
using Process process = new();
process.StartInfo.FileName = "Notepad.exe";
process.StartInfo.Arguments = filePath;
process.Start();
await process.WaitForExitAsync();
}
finally
{
File.Delete(filePath);
}
MessageBox.Show("Done!");
}
In the above example the UI remains responsive while the user interacts with the opened file. The UI thread would be blocked if the WaitForExit had been used instead.
I would probably not use a separate process for opening a file. Instead, I'd probably utilize a background thread (if I thought the operation was going to take a long time and possible block the UI thread).
private delegate void FileOpenDelegate(string filename);
public void OpenFile(string filename)
{
FileOpenDelegate fileOpenDelegate = OpenFileAsync;
AsyncCallback callback = AsyncCompleteMethod;
fileOpenDelegate.BeginInvoke(filename, callback, state);
}
private void OpenFileAsync(string filename)
{
// file opening code here, and then do whatever with the file
}
Of course, this is not a good working example (it returns nothing) and I haven't shown how the UI gets updated (you have to use BeginInvoke at the UI level because a background thread cannot update the UI thread). But this approach is generally how I go about handling asynchronous operations in .Net.
You can use the Exited event in Process class
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "notepad.exe";
Process process = Process.Start(info);
process.Exited += new EventHandler(process_Exited);
Console.Read();
and in that event you can handle the operations you mentioned