现在的位置: 首页 > 综合 > 正文

多线程 复习

2012年02月25日 ⁄ 综合 ⁄ 共 3415字 ⁄ 字号 评论关闭

简单的线程处理 及同步:

public class MuThread
{
    int a = 0;

    int i = 0;
    private volatile bool _run=true;
    public void method(object par)
    {
        while (_run)
        {
            Console.WriteLine("运行中"+par.ToString());
        }
        Console.WriteLine("已结束");
        
    }
    public void stop()
    {
        _run = false;
    }

    public void method1()
    {
        while (a < 100)
        {
            a++; Console.WriteLine("线程1输出:" + a);
        }
    }
    public void method2()
    {
        //当不加入线程同步代码的时候调用method1跟method2 会出现混乱
        //但是通过数他们的输出行数依然是100行 
        //说明while判断是正确的 
        //当CPU分配时间片的时候 无论他们有多么接近 其实同一时间依然只有一个线程在访问变量a

        //但是线程1跟2是CPU随机分配时间片交替前进的 实现同一时间多个进度协同执行任务的效果

        while (a < 100)
        {
            a++; Console.WriteLine("线程2输出:" + a);
        }
    }

    public void methodSyn1()
    {
        while (a < 100)
        {
            lock (this)
            {
                //意思是代码进入lock范围后 大括号内的代码将会被单独占用直到执行完
                //而不会临时被其他时间片插入导致a的值已经更改
                //当时间片继续回到此段时还沿用原来的 变量 导致混乱
                //如果去掉前面的判断 会输出101 ,至于原理么跟孙鑫C++线程同步是一样的 也有Monitor.Entry()
                if (a < 100)
                {
                    a++; Console.WriteLine("线程1输出:" + a);
                }
            }
        }
    }

    public void methodSyn2()
    {
        while (a < 100)
        {
            Monitor.Enter(this);
            if (a < 100)
            {
                a++; Console.WriteLine("线程2输出:" + a);
            }
            Monitor.Exit(this);
        }
    }
}

 

线程示例:

static void Main()
{
    //Service s = new Service();
    //s.start();

    //初始化MuThread的时候可以在构造函数 中传入一个方法引用也就是delegate
    //然后再MuThread实例的线程方法执行完毕后调用该delegate 
    //这种编程方式我一直认为很高深 被那些砖家称之为"回调"callback
    //参见ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_fxadvance/html/52b32222-e185-4f42-91a7-eaca65c0ab6d.htm
    MuThread m = new MuThread();

    //ThreadStart 其实是一个委托
    //在C++里就需要声明委托 
    //为了给方法传参数但是不能为每种类型都定义一个委托 所以只能传入object类型

    //.Net为我们简化了的语法
    Thread tPar = new Thread(m.method);
    tPar.Start("传入的参数");

    //ParameterizedThreadStart委托显示语法 start()其实相当于Event.do()            
    ParameterizedThreadStart del = new ParameterizedThreadStart(m.method);
    Thread tPar2 = new Thread(del);
    tPar2.Start("传入的参数");

    Thread t = new Thread(new ThreadStart(m.method1));
    Thread t2 = new Thread(new ThreadStart(m.method2));
    t2.Start();
    t.Start();
    //利用volatile 参数的状态终止线程
    while (!tPar.IsAlive) ;

    Thread.Sleep(100);
    m.stop();
    //MSDN的意思是阻断当前调用t的线程 也就是Main 主线程 直到让t执行完毕
    //事实确实是这样的 当不加Join()的时候 看着t.start()的语句在main方法下面的循环语句前面
    //其实他们的时间片依然由CPU随机分配的 "主线程调用"这句输出是穿插在前面子线程输出一起的
    //参见ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/fxref_mscorlib/html/56ed7b6f-efe0-67e7-34bc-766dd9f693f9.htm
    //当主线程 也就是Main方法里进行Thread.Sleep(200)时 其实是挂起主线程 这样就可以把时间片让给那些子线程
    t.Join();
    for (int i = 0; i < 50; i++)
    {
        Console.WriteLine("主线程调用");
    }

    //使用线程池
    //ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/dv_csref/html/5426dae4-c3f3-4e76-a998-19f7ca4baf3f.htm
    Console.ReadKey();
}

 

使用backgroundworker组件:

 

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        backgroundWorker1.WorkerReportsProgress = true;
        backgroundWorker1.WorkerSupportsCancellation = true;
        button3.Enabled = false;
    }

    private void button2_Click(object sender, EventArgs e)//start
    {
        textBox1.Text = "开始产生10000以内的随机数。。。\n\n";
        button2.Enabled = false;
        button3.Enabled = true;
        //在后台开始操作
        backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        //不要直接使用组件实例名称(backgroundworker1)因为有多个backgroundworker时
        //直接使用会产生耦合问题 应该通过下面的转换使用它
        BackgroundWorker worker = sender as BackgroundWorker;
        //下面的内容相当于线程要处理的内容。//注意 不要在此事件中和界面控件打交道
        Random r = new Random();
        int numCount = 0;
        while (worker.CancellationPending==false)
        {
            int num = r.Next(10000);
            if (num%5==0)
            {
                numCount++;
                worker.ReportProgress(0, num);
                Thread.Sleep(1000);
            }
        }
        e.Result = numCount;
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        int num = (int)e.UserState;
        textBox1.Text += num + " ";
    }

    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error==null)
        {
            textBox1.Text += "\n\n操作停止,共产生" + e.Result + "个能被5整除的随机数";
        }
        else
        {
            textBox1.Text += "\n操作过程中产生错误:" + e.Error;
        }
    }

    private void button3_Click(object sender, EventArgs e)
    {
        backgroundWorker1.CancelAsync();
        button3.Enabled = false;
        button2.Enabled = true;
    }

}

 

抱歉!评论已关闭.