C#线程开发之System.Thread类详解

 更新时间:2022年05月11日 10:56:08   作者:springsnow  
本文详细讲解了C#线程开发之System.Thread类,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一、属性

  • CurrentContext    获取线程正在其中执行的当前上下文。
  • ExecutionContext    获取 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。
  • CurrentCulture    获取或设置当前线程的区域性。
  • CurrentUICulture    获取或设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源。
  • CurrentThread    获取当前正在运行的线程。
  • IsAlive    获取指示当前线程的执行状态的值。
  • IsBackground    获取或设置一个值,该值指示某个线程是否为后台线程。
  • IsThreadPoolThread    获取指示线程是否属于托管线程池的值。
  • ManagedThreadId    获取当前托管线程的唯一标识符。
  • Name    获取或设置线程的名称。
  • Priority    获取或设置指示线程的调度优先级的值。
  • ThreadState    获取一个值,该值包含当前线程的状态。

二、创建和控制线程

Thread 类的构造函数重载为接受ThreadStart和ParameterizedThreadStart类型的委托参数。
ThreadStart委托定义了一个返回类型为void的无参数方法。在创建了 Thread对象后,就可以用Start()方法启动线程:

class Program
{
    static void Main()
    {
        var t1 = new Thread(ThreadMain);
        t1.Start();
        Console.WriteLine("This is the main thread.");
    }
    static void ThreadMain()
    {
        Console.WriteLine("Running in a thread.");
    }
}

Lambda表达式还可以与Thread类一起 使用,将线程方法的实现代码传送给Thread构造函数的实参:

static void Main()
{
    var t1 = new Thread(() => Console.WriteLine("running in a thread, id: {0}",Thread.CurrentThread.ManagedThreadId));
    t1.Start();
    Console.WriteLine("This is the main thread, id: {0}",
    Thread.CurrentThread.ManagedThreadId);
}

三、给线程传递参数

给线程传递一些数据可以采用两种方式。

1、ParameterizedThreadStart委托参数

要给线程传递数据,需要某个存储数据的类或结构。这里定义了包含字符串的Data结构,但可以传递任意对象.

static void Main()
{
    var d = new Data { Message = "Info" };
    var t2 = new Thread(ThreadMainWithParameters);//ParameterizedThreadStart委托实例
    t2.Start(d);
}
static void ThreadMainWithParameters(object o)//如果使用了 ParameterizedThreadStart委托,线程的入口点必须有一个object类型的参数,且返回类型为void。
{
    Data d = (Data)o;
    Console.WriteLine("Running in a thread, received {0}", d.Message);
}
public struct Data
{
    public string Message;
}

2、创建一个自定义类,把线程的方法定义为实例方法

给新线程传递数据的另一种方式是定义一个类(参见MyThread类),在其中定义需要的字段,将线程的调用的方法定义为类的一个实例方法:

static void Main()
{
    var obj = new MyThread("info");
    var t3 = new Thread(obj.ThreadMain);//实例方法
    t3.Start();
}
//实例方法
public class MyThread
{
    private string data;
    public MyThread(string data)
    {
        this.data = data;
    }
    public void ThreadMain()
    {
        Console.WriteLine("Running in a thread, data: {0}", data);
    }
}

四、后台线程

只要有一个前台线程在运行,应用程序的进程就在运行。
如果多个前台线程在运行,而Main()方法结束了,应用程序的进程就仍然是激活的,直到所有前台线程完成其任务为止。
在默认情况下,用Thread类创建的线程是前台线程。线程池屮的线程总是后台线程。
在用Thread类创建线程时,可以设置IsBackground属性,以确定该线程是前台线程还是后台线程。

五、线程的优先级

在Thread类中,可以设置Priority属性,以影响线程的基本优先级。Priority属性需要ThreadPriority 枚举定义的一个值。定义的级别有Highest、AboveNomal、BelowNormal和Lowest。

六、控制线程

  • 调用Thread对象的Start()方法,可以创建线程。但是,在调用Start()方法后,新线程仍不是处于Running状态,而是处于Unstarted状态。只要操作系统的线程调度器选择了要运行的线程,线程就会改为Running状态。读取Thread.ThreadState属性,就可以获得线程的当前状态。
  • 使用ThreadSleep()方法,会使线程处于WaitSleepJoin状态,在经历Sleep()方法定义的时间段后,线程就会等待再次被唤醒。
  • 要停止另一个线程,可以调用Thread.Abort() 方法。调用这个方法时,会在接到终止命令的线程中抛出一个ThreadAbortExcepticm类型的异常。用一个处理程序捕获这个异常,线程可以在结束前完成一些淸理工作。线程还可以在接收到调用Thread.ResetAbort()方法的结果ThreadAbortExcepdon 异常后继续运行。如果线程没有重置终止,接收到终止请求的线程的状态就从AbortRequested改为 Aborted。
  • 如果需要等待线程的结束,就可以调用Thread.Join()方法。Thread.Join()方法会停止当前线程, 并把它设置为WaitSleepJoin状态,直到加入的线程完成为止。
public class Worker
{
    // 此方法将在线程启动时调用。
    public void DoWork()
    {
        while (!_shouldStop)
        {
            Console.WriteLine("工作线程: working...");
        }
        Console.WriteLine("工作线程:正常停止");
    }
    public void RequestStop()
    {
        _shouldStop = true;
    }
    // Volatile用于提示编译器这个数据成员将被多个线程访问。
    private volatile bool _shouldStop;
}

static void Main()
{
    // 创建thread对象,但这不会启动线程。
    Worker workerObject = new Worker();
    Thread workerThread = new Thread(workerObject.DoWork);

    // 启动工作线程。
    workerThread.Start();
    Console.WriteLine("main thread: 启动工作线程...");

    // 循环,直到工作线程激活。
    while (!workerThread.IsAlive) ;

    // 将主线程休眠1毫秒,让工作线程做一些工作:
    Thread.Sleep(1);

    // 请求工作线程停止自身:
    workerObject.RequestStop();//workerObject.Abort()

    //使用Join方法阻塞当前线程,直到工作线程执行完毕才往下执行
    workerThread.Join();
    Console.WriteLine("main thread: 工作线程已经终止.");
}

七、使用线程实现回调

//定义一个委托实现回调函数 
public delegate void CallBackDelegate(string message);

void Main()
{
    //委托实现方法和定义线程
    CallBackDelegate cbd = CallBack;
    Thread thread = new Thread(initFtpParam);
    thread.Start(cbd);
}

/// <summary>
/// 线程方法
/// </summary>
/// <param name="obj"></param>
public void initFtpParam(object obj)
{
    CallBackDelegate callBackDelegate = obj as CallBackDelegate;
    callBackDelegate("aa");//执行委托
}

/// <summary>
/// 回调方法
/// </summary>
/// <param name="message"></param>
private void CallBack(string message)
{
    Console.Write(message);
}

八、区域性和线程

  • CurrentUICulture属性可返回当前用户界面区域性。该属性由 ResourceManager 类用于在运行时查找区域性特定资源。
    可以使用非特定区域性、特定区域性或 InvariantCulture 来设置 CurrentUICulture 属性。
    默认值是操作系统用户界面语言。
  • CurrentCulture属性用来决定诸如货币、数字和日期如何格式化。
    CurrentCulture 属性不是一个语言设置。它仅包含与地理区域的标准设置相关的数据。因此,只能将 CurrentCulture 属性设置为特定区域性,比如"fr-FR"或 InvariantCulture。
    默认值是操作系统的User Locale,我们可以在控制面板里设置。CultureInfo.UseUserOverride属性指示是否使用用户在控制面板自定义的 数字、符号、日期、货币等的格式。

1、.NET4.5之前,只能用以下代码只能针对单个线程,如果每次执行线程 都要重新设置一下。。。
新开一个新线程,默认的CurrentCulture为系统的Culture,如果要改变当前线程的Culture,需要在线程中修改 Thread.CurrentCulture值来实现。

m.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");

2、如果使用的.net环境是4.5及以上版本,CultureInfo提供了两个静态属性DefaultThreadCulture和DefaultThreadUICulture,一处修改即可实现所有的未显式设置Thread.CurrentCulture的线程都使用这个Default值。

System.Globalization.CultureInfo.DefaultThreadCurrentCulture = new System.Globalization.CultureInfo("en-US");
System.Globalization.CultureInfo.DefaultThreadCurrentUICulture = new System.Globalization.CultureInfo("en-US");

到此这篇关于C#线程开发之System.Thread类的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • c#序列化详解示例

    c#序列化详解示例

    序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据
    2014-02-02
  • 用C#来解析PDF文件

    用C#来解析PDF文件

    这篇文章主要介绍了用C#来解析PDF文件,同时作者也介绍了PdfFileAnalyzer这个应用可以作为很好的成品示例,需要的朋友可以参考下
    2015-07-07
  • 利用微软com组件mstscax.dll实现window7远程桌面功能

    利用微软com组件mstscax.dll实现window7远程桌面功能

    利用微软提供的com组件mstscax.dll实现类似window远程桌面功能,大家参考使用吧
    2013-12-12
  • C# 多线程编程技术基础知识入门

    C# 多线程编程技术基础知识入门

    这篇文章主要介绍了C# 多线程编程技术基础知识,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2020-02-02
  • Winform窗体传值的方法(示例)

    Winform窗体传值的方法(示例)

    C#开发windows应用程序项目时,不同窗口之间传值有很多中方法,在此给大家介绍两种比较常用的winform窗体传值的方法,有需要的朋友可以参考下
    2015-08-08
  • C# 使用SDL2实现Mp4文件播放音视频操作

    C# 使用SDL2实现Mp4文件播放音视频操作

    这篇文章主要介绍了C# 使用SDL2实现Mp4文件播放音视频操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • ASP.NET C#中Application的用法教程

    ASP.NET C#中Application的用法教程

    这篇文章主要给大家介绍了关于ASP.NET C#中Application的用法,在介绍Application的用法之前,先给大家介绍了Session的用法供大家参考学习,文中介绍的非常详细,需要的朋友们下面跟着小编一起来学习学习吧。
    2017-05-05
  • C#利用Random得随机数求均值、方差、正态分布的方法

    C#利用Random得随机数求均值、方差、正态分布的方法

    这篇文章主要介绍了C#利用Random得随机数求均值、方差、正态分布的方法,涉及C#数学运算及概率统计的相关技巧,需要的朋友可以参考下
    2015-05-05
  • C#获取Visio模型信息的简单方法示例

    C#获取Visio模型信息的简单方法示例

    这篇文章主要给大家介绍了关于C#获取Visio模型信息的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-11-11
  • C#网络编程之Socket编程

    C#网络编程之Socket编程

    本文详细讲解了C#网络编程的Socket编程,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02

最新评论