C# 在新线程中调用方法

Posted

技术标签:

【中文标题】C# 在新线程中调用方法【英文标题】:C# Call a method in a new thread 【发布时间】:2011-12-22 06:39:57 【问题描述】:

我正在寻找一种在新线程上调用方法的方法(使用 C#)。

例如,我想在一个新线程上调用SecondFoo()。但是,我希望在SecondFoo() 完成时终止线程。

我在C# 中看到了几个线程示例,但没有一个适用于我需要生成的线程自行终止的特定场景。这可能吗?

如何强制运行Secondfoo() 的衍生线程在完成后终止?

有人遇到过这样的例子吗?

【问题讨论】:

当 Secondfoo() 返回时,它正在运行的线程将终止。为什么你认为它没有? 有什么原因不能使用线程池吗? 【参考方案1】:

如果你真的启动了一个新线程,该线程在方法结束时终止:

Thread thread = new Thread(SecondFoo);
thread.Start();

现在SecondFoo将在新线程中被调用,线程完成后将终止。

您是否实际上的意思是希望线程在调用线程中的方法完成时终止?

编辑:请注意,启动线程是一项相当昂贵的操作。您肯定需要一个全新的 线程而不是使用线程池线程吗?考虑使用ThreadPool.QueueUserWorkItem 或(最好,如果您使用.NET 4)TaskFactory.StartNew

【讨论】:

就是这样 :-) 我不知道当没有更多语句要执行时线程终止。所以这就是我需要的确切答案。非常感谢!!!【参考方案2】:

它真的必须是一个线程,还是也可以是一个任务?

如果是这样,最简单的方法是:

Task.Factory.StartNew(() => SecondFoo());

【讨论】:

或者只是Task.Run @Omu 仍然必须确保 Tas.Run 满足性能需求 @Omu 是的,你是对的,任务更快。 Task.Run 的性能特别值得关注。见***.com/questions/18038776/…和blog.stephencleary.com/2013/11/… StartNew is Dangerous,请改用Task.Run【参考方案3】:

一旦线程启动,就没有必要保留对 Thread 对象的引用。线程继续执行,直到线程过程结束。

new Thread(new ThreadStart(SecondFoo)).Start();

【讨论】:

这段代码实际上创建了一个新线程,而不是线程池线程 谢谢亚历克斯。重新阅读我的答案后,我也很惊讶!已更正。【参考方案4】:

异步版本:

private async Task DoAsync()

    await Task.Run(async () =>
    
        //Do something awaitable here
    );

【讨论】:

【参考方案5】:

除非你有特殊情况需要非线程池线程,否则就使用这样的线程池线程:

Action secondFooAsync = new Action(SecondFoo);

secondFooAsync.BeginInvoke(new AsyncCallback(result =>
      
         (result.AsyncState as Action).EndInvoke(result); 

      ), secondFooAsync); 

保证调用 EndInvoke 来为您进行清理。

【讨论】:

我之前使用 beginInvoke 在新线程中运行长处理报告。这是一篇关于 BeginInvoke 的 MSDN 文章:msdn.microsoft.com/en-us/library/2e08f6yc%28v=vs.71%29.aspx【参考方案6】:

据我了解,您需要终止为Thread.Abort() 对吗?在这种情况下,您可以退出 Foo()。或者您可以使用Process 来捕获线程。

Thread myThread = new Thread(DoWork);

myThread.Abort();

myThread.Start(); 

流程示例:

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]);
    

【讨论】:

以上是关于C# 在新线程中调用方法的主要内容,如果未能解决你的问题,请参考以下文章

C++ 单线程工作,在新线程上它调用“abort()”

如何将 HttpContext 传递给新线程 c#

C#在不同线程的同一类中的父线程中调用方法

C# 异步方法加await调用不就变成同步方法了吗

将 UI Thread 方法传递给另一个线程以在 C# 中调用

C#线程调用方法时,怎么传参数过去