c#多线程编程基础实例解析

发布时间:2020-12-25编辑:脚本学堂
本文介绍下c#多线程编程的基本与实例代码,有研究c#多线程编程的朋友做个参考。
六、创建线程方式
通过搬运工案例我们能够了解线程的工作原理,也明白了线程的创建方式。
其实在C#中创建线程有几种方式。

例1,
 

复制代码 代码示例:
using System;
using System.Threading;
namespace MutiThreadSample
{
    /// <summary>
    /// 创建线程的方式
    /// </summary>
    class CreateThread
    {
        /// <summary>
        /// 不带参数的委托
        /// </summary>
        public void CreateThreadWithThreadStart()
        {
            Thread thread = new Thread(new ThreadStart(ThreadCallBack));
            thread.Start();
        }
        /// <summary>
        /// 带参数的委托
        /// </summary>
        public void CreateThreadWithParamThreadStart()
        {
            Thread thread = new Thread(new ParameterizedThreadStart(ThreadCallBackWithParam));
            thread.Start();
        }
        /// <summary>
        /// 匿名函数
        /// </summary>
        public void CreateThreadWithAnonymousFunction()
        {
            Thread thread = new Thread(delegate()
            {
                Console.WriteLine("进入子线程1");
                for (int i = 1; i < 4; ++i)
                {
                    Thread.Sleep(50);
                    Console.WriteLine("t+++++++子线程1+++++++++");
                }
                Console.WriteLine("退出子线程1");
            });
            thread.Start();
        }
        /// <summary>
        /// 直接赋值委托
        /// </summary>
        public void CreateThreadWithCallBack()
        {
            Thread _hThread = new Thread(ThreadCallBack);
            _hThread.Start();
        }
        /// <summary>
        /// 无参数的方法调用
        /// </summary>
        public void ThreadCallBack()
        {
            // Do Something
        }
        /// <summary>
        /// 带参数的方法
        /// </summary>
        /// <param name="obj"></param>
        public void ThreadCallBackWithParam(object obj)
        {
            // Do Something
        } 
    }
}
 

时钟线程
使用 TimerCallback 委托指定希望 Timer 执行的方法。 计时器委托在构造计时器时指定,并且不能更改。 此方法不在创建计时器的线程上执行,而是在系统提供的 ThreadPool 线程上执行。创建计时器时,可以指定在第一次执行方法之前等待的时间量(截止时间)以及此后的执行期间等待的时间量(时间周期)。 可以使用 Change 方法更改这些值或禁用计时器。
例2,
 

复制代码 代码示例:
using System;
using System.Threading;
class TimerExample
{
    static void Main()
    {
        // Create an event to signal the timeout count threshold in the
        // timer callback.
        AutoResetEvent autoEvent     = new AutoResetEvent(false);
        StatusChecker  statusChecker = new StatusChecker(10);
        // Create an inferred delegate that invokes methods for the timer.
        TimerCallback tcb = statusChecker.CheckStatus;
        // Create a timer that signals the delegate to invoke
        // CheckStatus after one second, and every 1/4 second
        // thereafter.
        Console.WriteLine("{0} Creating timer.n",
            DateTime.Now.ToString("h:mm:ss.fff"));
        Timer stateTimer = new Timer(tcb, autoEvent, 1000, 250);
        // When autoEvent signals, change the period to every
        // 1/2 second.
        autoEvent.WaitOne(5000, false);
        stateTimer.Change(0, 500);
        Console.WriteLine("nChanging period.n");
        // When autoEvent signals the second time, dispose of
        // the timer.
        autoEvent.WaitOne(5000, false);
        stateTimer.Dispose();
        Console.WriteLine("nDestroying timer.");
    }
}
class StatusChecker
{
    private int invokeCount;
    private int  maxCount;
    public StatusChecker(int count)
    {
        invokeCount  = 0;
        maxCount = count;
    }
    // This method is called by the timer delegate.
    public void CheckStatus(Object stateInfo)
    {
        AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
        Console.WriteLine("{0} Checking status {1,2}.",
            DateTime.Now.ToString("h:mm:ss.fff"),
            (++invokeCount).ToString());
        if(invokeCount == maxCount)
        {
            // Reset the counter and signal Main.
            invokeCount  = 0;
            autoEvent.Set();
        }
    }
}

七、前台线程和后台线程
.Net的公用语言运行时(Common Language Runtime,CLR)能区分两种不同类型的线程:前台线程和后台线程。这两者的区别就是:应用程序必须运行完所有的前台线程才可以退出;而对于后台线程,应用程序则可以不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出时都会自动结束。
一个线程是前台线程还是后台线程可由它的IsBackground属性来决定。这个属性是可读又可写的。它的默认值为false,即意味着一个线程默认为前台线程。
我们可以将它的IsBackground属性设置为true,从而使之成为一个后台线程。下面的例子是一个控制台程序,程序一开始便启动了10个线程,每个线程运行5秒钟时间。由于线程的IsBackground属性默认为false,即它们都是前台线程,所以尽管程序的主线程很快就运行结束了,但程序要到所有已启动的线程都运行完毕才会结束。示例代码如下例子中的Test()所示:
 

复制代码 代码示例:
using System;
using System.Threading;
namespace MutiThreadSample.ThreadType
{
    class ThreadTypeTest
    {
        /// <summary>
        /// 测试前台线程
        /// </summary>
        public static void Test()
        {
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ThreadStart(ThreadFunc));
                thread.Start();
            }
        }
        /// <summary>
        /// 测试后台线程
        /// </summary>
        public static void TestBackgroundThread()
        {
            for (int i = 0; i < 10; i++)
            {
                Thread thread = new Thread(new ThreadStart(ThreadFunc));
                thread.IsBackground = true;
                thread.Start();
            }
        }
        public static void ThreadFunc()
        {
            Thread.Sleep(0);
            DateTime start = DateTime.Now;
            while ((DateTime.Now - start).Seconds < 20);//可以停顿的时间长一点,效果更加明显
        }
    }
}
 

接下来对上面的代码进行略微修改,将每个线程的IsBackground属性都设置为true,则每个线程都是后台线程了。那么只要程序的主线程结束了,整个程序也就结束了。示例代码如代码中的TestBackgroundThread()。
这个例子直接创建一个控制台程序即可检验。

前台和后台线程的使用原则
既然前台线程和后台线程有这种差别,那么我们怎么知道该如何设置一个线程的IsBackground属性呢?下面是一些基本的原则:对于一些在后台运行的线程,当程序结束时这些线程没有必要继续运行了,那么这些线程就应该设置为后台线程。比如一个程序启动了一个进行大量运算的线程,可是只要程序一旦结束,那个线程就失去了继续存在的意义,那么那个线程就该是作为后台线程的。

而对于一些服务于用户界面的线程往往是要设置为前台线程的,因为即使程序的主线程结束了,其他的用户界面的线程很可能要继续存在来显示相关的信息,所以不能立即终止它们。这里我只是给出了一些原则,具体到实际的运用往往需要编程者的进一步仔细斟酌。

八、总结

以上主要介绍多线程技术的基本知识。涉及多线程的具体应用,包括预防死锁、线程同步、线程池等,在今后的文章会涉及到。

>>> 您可能感兴趣的文章:
C# 多线程复制文件并显示进度条的代码
C# 多线程更新进度条progressBar控件的代码一例
c# 多线程操作progressBar进度条控件的例子
c# asp.net 多线程实例(经典)
c#多线程读取注册表 c#多线程的小例子