54

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?

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
Brett
  • 11,637
  • 34
  • 127
  • 213

6 Answers6

100

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.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    This is it :-) I was unaware that a thread terminates when there are no more statements to execute. So this is the exact answer I was in need of. Many thanks!!! – Brett Nov 04 '11 at 18:29
72

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());
dbc
  • 104,963
  • 20
  • 228
  • 340
Ron Sijm
  • 8,490
  • 2
  • 31
  • 48
  • 6
    or just `Task.Run` – Omu Mar 07 '18 at 15:20
  • @Omu still have to ensure that the Tas.Run fits the need as it comes with a performance hit – Samuel Sep 15 '18 at 21:29
  • @Omu yes you're right, Task is faster. Task.Run 's performance specifically is what should watch out for . see https://stackoverflow.com/questions/18038776/will-task-run-make-any-difference-in-performance and https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html – Samuel Sep 16 '18 at 06:48
  • 1
    [StartNew is Dangerous](https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html), use `Task.Run` instead. – Theodor Zoulias Dec 17 '21 at 00:16
  • @TheodorZoulias - This answer of mine was posted in 2011 where the context was DotNet3. You're also posting a link to an article from 2013 in 2021. Don't know if updating any of this is still relevant – Ron Sijm Mar 31 '22 at 20:57
  • 1
    Ron I think it's relevant. People are coming here to find code that works. There are not coming to see exhibits in a museum! Take a look at this: [CA2008: Do not create tasks without passing a TaskScheduler](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca2008) – Theodor Zoulias Mar 31 '22 at 21:15
12

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();
Artak
  • 2,819
  • 20
  • 31
6

Asynchronous version:

private async Task DoAsync()
{
    await Task.Run(async () =>
    {
        //Do something awaitable here
    });
}
John Deer
  • 2,033
  • 2
  • 13
  • 16
2

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.

Sean Thoman
  • 7,429
  • 6
  • 56
  • 103
  • I have used beginInvoke before to run a long processing report in a new thread. Here is an MSDN article on BeginInvoke: http://msdn.microsoft.com/en-us/library/2e08f6yc%28v=vs.71%29.aspx – William Nov 04 '11 at 18:31
-3

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]);
    }
}
Nasenbaer
  • 4,810
  • 11
  • 53
  • 86