码迷,mamicode.com
首页 > 编程语言 > 详细

C#读书笔记:线程,任务和同步

时间:2017-07-19 20:38:59      阅读:255      评论:0      收藏:0      [点我收藏+]

标签:多个   编程技巧   started   实现   exce   另一个   size   app   ini   

前言

学习C#两个多月了,像当初实习做PHP开发一样,也是由着一个个Feature需求,慢慢掌握了很多相关的编程技巧。本次主要记录下学习C# 多线程的相关知识。

 

参考书籍:《Csharp高级编程(第7版)》

 

1.使用线程的原因

 技术分享

不过运行多个线程也要注意一些问题:他们可以同时运行,但是如果线程访问相同的数据,就很容易出问题,必须实现同步机制

 2.理解线程

 线程是程序中独立的指令流。C#编写的程序都有一个入口点(即Main()方法),程序从该方法的第一条开始执行,直到方法返回为止。这种程序结构非常适合用于一个有任务序列的程序,但是程序常常需要同时完成多个任务。

这就要用到多个线程,比如Word的拼写检查器的工作原理是这样的:一个线程等待用户输入,另一个线程进行后台搜索,第3个线程将写入的数据保存在临时文件中,第4个线程从Internet上下载其他数据。

理解线程很重要的一点其实是理解线程和进程的关系:

 技术分享

3.创建线程的方式

  • 异步委托

创建线程的一种简单地方式是定义委托,并异步调用它。委托是方法的类型安全的引用,它使用线程池来完成异步任务。

代码实例:

使用投票的例子,并检查委托是否完成了它的任务。等待异步委托结果的四种方式:

(1)轮询

Delegate类提供了BeginInvoke()方法,通过其返回类型IAsyncResult ,可以获取委托的相关信息,并检验它是否完成了任务。只要委托没有完成其任务,程序的主线程就继续执行while循环。

(2)等待句柄

使用与IAsyncResult 相关联的等待句柄。使用AsyncWaitHandle属性可以访问等待句柄,该属性可以返回一个WaitHandle类型的对象,它可以等待委托线程完成其任务。

(3)异步回调

(4)Lambda表达式 

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace Wrox.ProCSharp.Threading
{
    class Program
    {
        static int TakesAWhile(int data, int ms)
        {
            Console.WriteLine("TakesAWhile started");
            Thread.Sleep(ms);
            Console.WriteLine("TakesAWhile completed");
            return ++data;
        }

     //要从委托中调用这个方法,必须定义一个有相同参数和返回类型的的委托 public delegate int TakesAWhileDelegate(int data, int ms); static void Main() { // synchronous // TakesAWhile(1, 3000); TakesAWhileDelegate d1 = TakesAWhile; // (1)polling轮询 //IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null); //while (!ar.IsCompleted) //{ // // doing something else // Console.Write("."); // Thread.Sleep(50); //} //int result = d1.EndInvoke(ar); //Console.WriteLine("result: {0}", result); // (2)wait handle //IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null); //while (true) //{ // Console.Write("."); // if (ar.AsyncWaitHandle.WaitOne(50, false)) // { // Console.WriteLine("Can get the result now"); // break; // } //} //int result = d1.EndInvoke(ar); //Console.WriteLine("result: {0}", result); // (3)async callback //d1.BeginInvoke(1, 3000, TakesAWhileCompleted, d1); //for (int i = 0; i < 100; i++) //{ // Console.Write("."); // Thread.Sleep(50); //} //(4)Lambda expression:可以直接访问作用域外的变量d1,所以不需要把一个值赋予BeginInvoke()方法的最后一个参数 d1.BeginInvoke(1, 3000, ar => { int result = d1.EndInvoke(ar); Console.WriteLine("result: {0}", result); }, null); for (int i = 0; i < 100; i++) { Console.Write("."); Thread.Sleep(50); } } static void TakesAWhileCompleted(IAsyncResult ar) { if (ar == null) throw new ArgumentNullException("ar"); TakesAWhileDelegate d1 = ar.AsyncState as TakesAWhileDelegate; Trace.Assert(d1 != null, "Invalid object type"); int result = d1.EndInvoke(ar); Console.WriteLine("result: {0}", result); } } }

运行结果:

技术分享

 

  

 

ps:在运行书中附带的sample时,报错:

技术分享

经查证,发现这是由于StartupUri中的内容与窗口名称不一致所导致。

技术分享

这部分的知识可以参考一篇译文:WPF教程(十)使用App.xaml

 

C#读书笔记:线程,任务和同步

标签:多个   编程技巧   started   实现   exce   另一个   size   app   ini   

原文地址:http://www.cnblogs.com/carsonzhu/p/7207556.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!