ylbtech-LanguageSamples-Threading(线程处理)

ylbtech-Microsoft-CSharpSamples:ylbtech-LanguageSamples-Threading(线程处理)

 

1.A,示例(Sample) 返回顶部

“线程处理”示例

本示例演示了下面的线程处理技术。有关更多信息,请参见线程处理(C# 编程指南) 。

  • 创建、启动和终止线程

  • 使用线程池

  • 线程同步和互交

安全说明

提供此代码示例是为了阐释一个概念,它并不代表最安全的编码实践,因此不应在应用程序或网站中使用此代码示例。对于因将此代码示例用于其他用途而出现的偶然或必然的损害,Microsoft 不承担任何责任。

在 Visual Studio 中生成并运行“线程处理”示例

  1. 在“解决方案资源管理器”中,右击“ThreadStartStop”项目并单击“设为启动项目”。

  2. 在“调试”菜单上,单击“开始执行(不调试)”。

  3. 对于 ThreadPool 和 ThreadSync,分别重复上述步骤。

从命令行生成并运行“线程”示例

  1. 使用“更改目录”命令转到“Threads”目录。

  2. 键入以下命令:

    cd ThreadStartStop
    
    csc ThreadStartStop.cs
    
    ThreadStartStop
  3. 键入以下命令:

    cd ..\ThreadPool
    
    csc ThreadPool.cs
    
    ThreadPool
  4. 键入以下命令:

    cd ..\ThreadSync
    
    csc ThreadSync.cs
    
    ThreadSync
1.B,ThreadStartStop 示例代码(Sample Code)返回顶部

1.B.1, ThreadStartStop.cs

ylbtech-LanguageSamples-Threading(线程处理)
// 版权所有(C) Microsoft Corporation。保留所有权利。

// 此代码的发布遵从

// Microsoft 公共许可(MS-PL,http://opensource.org/licenses/ms-pl.html)的条款。

//

//版权所有(C) Microsoft Corporation。保留所有权利。



using System;

using System.Threading;



public class Worker

{

    // 启动线程时调用此方法。

    public void DoWork()

    {

        while (!_shouldStop)

        {

            Console.WriteLine("worker thread: working...");

        }

        Console.WriteLine("worker thread: terminating gracefully.");

    }

    public void RequestStop()

    {

        _shouldStop = true;

    }

    // Volatile 用于向编译器提示此数据

    // 成员将由多个线程访问。

    private volatile bool _shouldStop;

}



public class WorkerThreadExample

{

    static void Main()

    {

        // 创建线程对象。这不会启动该线程。

        Worker workerObject = new Worker();

        Thread workerThread = new Thread(workerObject.DoWork);



        // 启动辅助线程。

        workerThread.Start();

        Console.WriteLine("main thread: Starting worker thread...");



        // 循环直至辅助线程激活。

        while (!workerThread.IsAlive);



        // 为主线程设置 1 毫秒的休眠,

        // 以使辅助线程完成某项工作。

        Thread.Sleep(1);



        // 请求辅助线程自行停止:

        workerObject.RequestStop();



        // 使用 Join 方法阻塞当前线程, 

        // 直至对象的线程终止。

        workerThread.Join();

        Console.WriteLine("main thread: Worker thread has terminated.");

    }

}
View Code

1.B.2,

1.B.EXE,

main thread: Starting worker thread...

worker thread: working...

worker thread: working...

worker thread: working...

worker thread: working...

worker thread: working...

worker thread: working...

worker thread: working...

worker thread: working...

worker thread: terminating gracefully.

main thread: Worker thread has terminated.

请按任意键继续. . .

1.B

1.B,ThreadPool 示例代码2(Sample Code)返回顶部

1.B.1, ThreadPool.cs

ylbtech-LanguageSamples-Threading(线程处理)
// 版权所有(C) Microsoft Corporation。保留所有权利。

// 此代码的发布遵从

// Microsoft 公共许可(MS-PL,http://opensource.org/licenses/ms-pl.html)的条款。

//

//版权所有(C) Microsoft Corporation。保留所有权利。



using System;

using System.Threading;



// Fibonacci 类为使用辅助

// 线程执行长时间的 Fibonacci(N) 计算提供了一个接口。

// N 是为 Fibonacci 构造函数提供的,此外还提供了

// 操作完成时对象发出的事件信号。

// 然后,可以使用 FibOfN 属性来检索结果。

public class Fibonacci

{

    public Fibonacci(int n, ManualResetEvent doneEvent)

    {

        _n = n;

        _doneEvent = doneEvent;

    }



    // 供线程池使用的包装方法。

    public void ThreadPoolCallback(Object threadContext)

    {

        int threadIndex = (int)threadContext;

        Console.WriteLine("thread {0} started...", threadIndex);

        _fibOfN = Calculate(_n);

        Console.WriteLine("thread {0} result calculated...", threadIndex);

        _doneEvent.Set();

    }



    // 计算第 N 个斐波纳契数的递归方法。

    public int Calculate(int n)

    {

        if (n <= 1)

        {

            return n;

        }

        else

        {

            return Calculate(n - 1) + Calculate(n - 2);

        }

    }



    public int N { get { return _n; } }

    private int _n;



    public int FibOfN { get { return _fibOfN; } }

    private int _fibOfN;



    ManualResetEvent _doneEvent;

}



public class ThreadPoolExample

{

    static void Main()

    {

        const int FibonacciCalculations = 10;



        // 每个 Fibonacci 对象使用一个事件

        ManualResetEvent[] doneEvents = new ManualResetEvent[FibonacciCalculations];

        Fibonacci[] fibArray = new Fibonacci[FibonacciCalculations];

        Random r = new Random();



        // 使用 ThreadPool 配置和启动线程:

        Console.WriteLine("launching {0} tasks...", FibonacciCalculations);

        for (int i = 0; i < FibonacciCalculations; i++)

        {

            doneEvents[i] = new ManualResetEvent(false);

            Fibonacci f = new Fibonacci(r.Next(20,40), doneEvents[i]);

            fibArray[i] = f;

            ThreadPool.QueueUserWorkItem(f.ThreadPoolCallback, i);

        }



        // 等待池中的所有线程执行计算...

        WaitHandle.WaitAll(doneEvents);

        Console.WriteLine("Calculations complete.");



        // 显示结果...

        for (int i= 0; i<FibonacciCalculations; i++)

        {

            Fibonacci f = fibArray[i];

            Console.WriteLine("Fibonacci({0}) = {1}", f.N, f.FibOfN);

        }

    }

}
View Code

1.B.2,

1.B.EXE,

ylbtech-LanguageSamples-Threading(线程处理)
launching 10 tasks...

thread 0 started...

thread 1 started...

thread 1 result calculated...

thread 2 started...

thread 2 result calculated...

thread 3 started...

thread 0 result calculated...

thread 4 started...

thread 4 result calculated...

thread 5 started...

thread 5 result calculated...

thread 6 started...

thread 6 result calculated...

thread 7 started...

thread 7 result calculated...

thread 8 started...

thread 8 result calculated...

thread 9 started...

thread 3 result calculated...

thread 9 result calculated...

Calculations complete.

Fibonacci(27) = 196418

Fibonacci(23) = 28657

Fibonacci(21) = 10946

Fibonacci(38) = 39088169

Fibonacci(25) = 75025

Fibonacci(25) = 75025

Fibonacci(37) = 24157817

Fibonacci(27) = 196418

Fibonacci(29) = 514229

Fibonacci(37) = 24157817

请按任意键继续. . .
View Code

1.B,

1.B,ThreadSync 示例代码3(Sample Code)返回顶部

1.B.1, ThreadSync.cs

ylbtech-LanguageSamples-Threading(线程处理)
// 版权所有(C) Microsoft Corporation。保留所有权利。

// 此代码的发布遵从

// Microsoft 公共许可(MS-PL,http://opensource.org/licenses/ms-pl.html)的条款。

//

//版权所有(C) Microsoft Corporation。保留所有权利。



using System;

using System.Threading;

using System.Collections;

using System.Collections.Generic;



// 将线程同步事件封装在此类中, 

// 以便于将这些事件传递给 Consumer 和

// Producer 类。

public class SyncEvents

{

    public SyncEvents()

    {

        // AutoResetEvent 用于“新项”事件,因为

        // 我们希望每当使用者线程响应此事件时,

        // 此事件就会自动重置。

        _newItemEvent = new AutoResetEvent(false);



        // ManualResetEvent 用于“退出”事件,因为

        // 我们希望发出此事件的信号时有多个线程响应。

        // 如果使用 AutoResetEvent,事件

        // 对象将在单个线程作出响应之后恢复为 

        // 未发信号的状态,而其他线程将

        // 无法终止。

        _exitThreadEvent = new ManualResetEvent(false);



        // 这两个事件也放在一个 WaitHandle 数组中,以便

        // 使用者线程可以使用 WaitAny 方法

        // 阻塞这两个事件。

        _eventArray = new WaitHandle[2];

        _eventArray[0] = _newItemEvent;

        _eventArray[1] = _exitThreadEvent;

    }



    // 公共属性允许对事件进行安全访问。

    public EventWaitHandle ExitThreadEvent

    {

        get { return _exitThreadEvent; }

    }

    public EventWaitHandle NewItemEvent

    {

        get { return _newItemEvent; }

    }

    public WaitHandle[] EventArray

    {

        get { return _eventArray; }

    }



    private EventWaitHandle _newItemEvent;

    private EventWaitHandle _exitThreadEvent;

    private WaitHandle[] _eventArray;

}



// Producer 类(使用一个辅助线程)

// 将项异步添加到队列中,共添加 20 个项。

public class Producer 

{

    public Producer(Queue<int> q, SyncEvents e)

    {

        _queue = q;

        _syncEvents = e;

    }

    public void ThreadRun()

    {

        int count = 0;

        Random r = new Random();

        while (!_syncEvents.ExitThreadEvent.WaitOne(0, false))

        {

            lock (((ICollection)_queue).SyncRoot)

            {

                while (_queue.Count < 20)

                {

                    _queue.Enqueue(r.Next(0, 100));

                    _syncEvents.NewItemEvent.Set();

                    count++;

                }

            }

        }

        Console.WriteLine("Producer thread: produced {0} items", count);

    }

    private Queue<int> _queue;

    private SyncEvents _syncEvents;

}



// Consumer 类通过自己的辅助线程使用队列

// 中的项。Producer 类使用 NewItemEvent 

// 将新项通知 Consumer 类。

public class Consumer

{

    public Consumer(Queue<int> q, SyncEvents e)

    {

        _queue = q;

        _syncEvents = e;

    }

    public void ThreadRun()

    {

        int count = 0;

        while (WaitHandle.WaitAny(_syncEvents.EventArray) != 1)

        {

            lock (((ICollection)_queue).SyncRoot)

            {

                int item = _queue.Dequeue();

            }

            count++;

        }

        Console.WriteLine("Consumer Thread: consumed {0} items", count);

    }

    private Queue<int> _queue;

    private SyncEvents _syncEvents;

}



public class ThreadSyncSample

{

    private static void ShowQueueContents(Queue<int> q)

    {

        // 对集合进行枚举本来就不是线程安全的,

        // 因此在整个枚举过程中锁定集合以防止

        // 使用者和制造者线程修改内容

        // 是绝对必要的。(此方法仅由

        // 主线程调用。)

        lock (((ICollection)q).SyncRoot)

        {

            foreach (int i in q)

            {

                Console.Write("{0} ", i);

            }

        }

        Console.WriteLine();

    }



    static void Main()

    {

        // 配置结构,该结构包含线程同步

        // 所需的事件信息。

        SyncEvents syncEvents = new SyncEvents();



        // 泛型队列集合用于存储要制造和使用的

        // 项。此例中使用的是“int”。

        Queue<int> queue = new Queue<int>();



        // 创建对象,一个用于制造项,一个用于

        // 使用项。将队列和线程同步事件传递给

        // 这两个对象。

        Console.WriteLine("Configuring worker threads...");

        Producer producer = new Producer(queue, syncEvents);

        Consumer consumer = new Consumer(queue, syncEvents);



        // 为制造者对象和使用者对象创建线程

        // 对象。此步骤并不创建或启动

        // 实际线程。

        Thread producerThread = new Thread(producer.ThreadRun);

        Thread consumerThread = new Thread(consumer.ThreadRun);



        // 创建和启动两个线程。

        Console.WriteLine("Launching producer and consumer threads...");        

        producerThread.Start();

        consumerThread.Start();



        // 为制造者线程和使用者线程设置 10 秒的运行时间。

        // 使用主线程(执行此方法的线程)

        // 每隔 2.5 秒显示一次队列内容。

        for (int i = 0; i < 4; i++)

        {

            Thread.Sleep(2500);

            ShowQueueContents(queue);

        }



        // 向使用者线程和制造者线程发出终止信号。

        // 这两个线程都会响应,由于 ExitThreadEvent 是

        // 手动重置的事件,因此除非显式重置,否则将保持“设置”。

        Console.WriteLine("Signaling threads to terminate...");

        syncEvents.ExitThreadEvent.Set();



        // 使用 Join 阻塞主线程,首先阻塞到制造者线程

        // 终止,然后阻塞到使用者线程终止。

        Console.WriteLine("main thread waiting for threads to finish...");

        producerThread.Join();

        consumerThread.Join();

    }

}
View Code

1.B.2,

1.B.EXE,

Configuring worker threads...

Launching producer and consumer threads...

87 65 95 1 77 97 21 64 77 43 50 63 4 99 84 29 5 26 35

41 15 71 91 26 56 21 21 18 51 15 9 25 50 5 65 82 76 99

99 23 41 24 6 80 37 95 87 52 83 96 86 67 34 47 10 42 44 17

40 10 44 38 75 35 85 85 92 33 25 33 86 48 12 99 7 92 36 17

Signaling threads to terminate...

main thread waiting for threads to finish...

Producer thread: produced 2015587 items

Consumer Thread: consumed 2015568 items

请按任意键继续. . .

1.B,

1.C,下载地址(Free Download)返回顶部

 

warn 作者:ylbtech
出处:http://ylbtech.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

你可能感兴趣的:(language)