• 线程


    hei 7

    0
    t 是一个线程
    //这句话(t.Join();)在那个线程中执行,那么就阻塞了那个线程,那个线程要等待t线程执行完毕后,然后才会继续。
    t.Join();//阻塞当前"主线程",等待t线程执行完毕后,继续主线程的执行。
    t.Join(1000); //1000表示超时时间,这里“主线程”会等待t线程执行完毕,只等待1000毫秒,超过1000毫秒后,“主线程”继续执行。


    1 线程池的作用
    //线程池的使用:
    ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
    {
    Console.WriteLine("方法三:" + Thread.CurrentThread.ManagedThreadId);
    //这里的方法就是要进行异步执行的方法
    for (int i = 0; i < 10; i++)
    {
    Console.WriteLine("*");
    Thread.Sleep(300);
    }
    }));


    1 子线程改变主线程控件的方法

    #region 子线程给主线程设置控件值
    private string UpdatText(string msg)
    {
    richTextBox1.AppendText(msg + " ");
    return msg;
    }

    public void ThreadMethodTxt(string n)
    {
    IAsyncResult ar= this.BeginInvoke(updateText, n);
    string res = this.EndInvoke(ar).ToString();

    this.BeginInvoke(updateText, "返回数据" + res);
    }

    //创建一个委托,是为访问TextBox控件服务的。
    public delegate string UpdateText(string msg);
    /// <summary>
    /// 定义一个委托变量
    /// </summary>
    public UpdateText updateText = null;
    /// <summary>
    /// 子线程给主线程赋值
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button1_Click(object sender, EventArgs e)
    {
    updateText = new UpdateText(UpdatText);
    Thread objThread = new Thread(new ThreadStart(delegate()
    {
    ThreadMethodTxt(textBox1.Text);

    }));

    objThread.IsBackground = true;
    objThread.Start();
    }

    #endregion


    1.1 子线程改变主线程的方法(抽奖机的运用)

    private void button1_Click(object sender, EventArgs e)
    {
    List<Label> listLabel = new List<Label>();
    List<Thread> listThread = new List<Thread>();
    Random rdm = new Random();

    if (listThread.Count == 0)
    {
    //开始启动线程
    //有几个Label就创建几个线程
    for (int i = 0; i < listLabel.Count; i++)
    {
    Thread t = new Thread(new ParameterizedThreadStart((index) =>
    {
    //index这个参数就表示当前这个线程要修改的Label的索引
    while (true)
    {
    int r = rdm.Next(0, 10);
    //这里不能直接使用该Label控件,这样的话就会出现“跨线程访问控件”的问题
    //listLabel[(int)index].Text = r.ToString();
    //解决:使用控件的Invoke()方法
    listLabel[(int)index].Invoke(new Action<int, string>((lblIndex, randomVal) =>
    {
    listLabel[lblIndex].Text = randomVal;
    }), index, r.ToString());
    Thread.Sleep(50);
    }
    }));
    listThread.Add(t);
    t.IsBackground = true;
    t.Start(i);//启动线程的时候把当前循环的Label的下标传进来。
    }
    }

    }

    2 通过启动一新线程,执行带返回值的方法BackgroundWorker


    #region 通过启动一新线程,执行带返回值的方法BackgroundWorker


    Console.WriteLine("Main(string[] args)方法中:当前执行的线程编号:{0}", Thread.CurrentThread.ManagedThreadId);

    //BackgroundWorker
    //创建一个后台执行者对象
    BackgroundWorker backWorker = new BackgroundWorker();
    //设置该对象要在后台执行的方法
    backWorker.DoWork += new DoWorkEventHandler(backWorker_DoWork);

    //设置另外一个事件:当程序执行完毕后触发的事件
    backWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backWorker_RunWorkerCompleted);

    //开始执行
    backWorker.RunWorkerAsync(new int[] { 1, 100 });
    Console.WriteLine("主线程继续.......");
    Console.ReadKey();
    //Task

    #endregion

    //当后台方法执行完毕后触发的事件
    static void backWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    Console.WriteLine("backWorker_RunWorkerCompleted方法中:当前执行的线程编号:{0}", Thread.CurrentThread.ManagedThreadId);
    Console.WriteLine("最后输出结果是:{0}", e.Result);
    }


    //要在后台执行的方法
    static void backWorker_DoWork(object sender, DoWorkEventArgs e)
    {
    Console.WriteLine("backWorker_DoWork方法中:当前执行的线程编号:{0}", Thread.CurrentThread.ManagedThreadId);
    if (e.Argument != null)
    {
    int[] arr = e.Argument as int[];
    //把方法调用完毕后的值赋值给e.Result
    e.Result = Sum(arr[0], arr[1]);
    }

    }
    static int Sum(int from, int to)
    {
    int sum = 0;
    for (int i = from; i <= to; i++)
    {
    sum += i;
    }
    return sum;
    }

    3 拷贝文件的进度条

    private void button1_Click(object sender, EventArgs e)
    {
    //初始化进度条
    InitialProgressBar();


    //创建一个独立的线程来执行文件拷贝操作,这样就可以防止阻塞主线程了。
    Thread t1 = new Thread(new ThreadStart(() =>
    {
    //拷贝文件
    string source = textBox1.Text.Trim();
    string target = textBox2.Text.Trim();
    FileCopy(source, target);
    }));
    t1.Start();


    }

    private void InitialProgressBar()
    {
    this.progressBar1.Maximum = 100;
    this.progressBar1.Minimum = 0;
    this.progressBar1.Value = 0;
    }

    private void FileCopy(string source, string target)
    {
    using (FileStream fsRead = File.OpenRead(source))
    {
    using (FileStream fsWrite = File.OpenWrite(target))
    {
    //缓冲区
    byte[] buffers = new byte[1024 * 1024 * 10];//10MB
    //读取一次
    int r = fsRead.Read(buffers, 0, buffers.Length);
    //判断本次是否读取到了数据
    while (r > 0)
    {
    //把读取到的数据写入到fsWrite中
    fsWrite.Write(buffers, 0, r);
    int val = (int)(fsWrite.Position * 1.0 / fsRead.Length * 100);
    //progressBar1.Value = (int)(fsWrite.Position * 1.0 / fsRead.Length * 100);
    progressBar1.Invoke(new Action<int>(v =>
    {
    progressBar1.Value = v;
    }), val);


    r = fsRead.Read(buffers, 0, buffers.Length);
    }
    }
    }
    this.Invoke(new Action(() =>
    {
    this.Text = "拷贝完毕!";
    }));
    }


    4 线程并行计算


    Stopwatch watch = new Stopwatch();
    watch.Start();
    Parallel.For(0, 5, new Action<int>(i =>
    {
    Console.WriteLine("===" + Thread.CurrentThread.ManagedThreadId + "===");
    Console.WriteLine(i);
    Thread.Sleep(1000);
    }));
    watch.Stop();
    Console.WriteLine(watch.Elapsed);
    Console.ReadKey();

    5 线程池

    1 //////WaitCallback
    //////线程启动线程都是默认 后台线程。
    //////交给线程池的工作任务执行顺序是不确定。
    ThreadPool.QueueUserWorkItem(delegate(object state)
    {

    Console.WriteLine(state.ToString()+"当前执行的线程是:"+Thread.CurrentThread.ManagedThreadId);
    }, "ssss");

    2 ThreadPool.QueueUserWorkItem(new WaitCallback((s) =>
    {
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    }));

    //int maxThread = 0;
    //int maxCompleteThread = 0;

    //ThreadPool.GetMaxThreads(out maxThread,out maxCompleteThread);

    //Console.WriteLine(maxThread+" " +maxCompleteThread);

    6 Task 4.0 才有的新功能,是在线程池中的线程

    6.1
    //这里面使用的线程是线程池里面的线程

    //第一种开启一个线程池工作任务的方法
    Task t1 = new Task(() =>
    {
    Thread.Sleep(2000);
    Console.WriteLine("当前的线程是:"+Thread.CurrentThread.ManagedThreadId);

    });
    t1.Start();
    t1.Wait();//让当前主线程停下来等待 工作任务完成。

    6.2
    //第二种开始一个线程池工作任务项
    Task t1 = Task.Factory.StartNew(() =>//开启一个线程池工作任务,并执行了。
    {
    Thread.Sleep(2000);
    Console.WriteLine("当前的线程是:" + Thread.CurrentThread.ManagedThreadId);

    });
    t1.Wait();//让当前主线程停下来等待 工作任务完成。

    6.3
    //第二种开始一个线程池工作任务项
    Task t1 = Task.Factory.StartNew(() =>//开启一个线程池工作任务,并执行了。
    {
    Thread.Sleep(2000);
    Console.WriteLine("当前的线程是:" + Thread.CurrentThread.ManagedThreadId);

    });


    Task t2 = Task.Factory.StartNew(() =>//开启一个线程池工作任务,并执行了。
    {
    Thread.Sleep(2000);
    Console.WriteLine("当前的线程是:" + Thread.CurrentThread.ManagedThreadId);

    });


    Task t3 = Task.Factory.StartNew(() =>//开启一个线程池工作任务,并执行了。
    {
    Thread.Sleep(3000);
    Console.WriteLine("当前的线程是:" + Thread.CurrentThread.ManagedThreadId);

    });
    Task.WaitAny(t1, t2, t3);//WaitAny:等其中一个工作任务完成就往下执行。

    //WaitAll:是等待所有的线程工作任务都完成后再往下走。

    #region 线程通知
    //AutoResetEvent 线程安全类
    private static AutoResetEvent waitHand = new AutoResetEvent(false); //像构造函数中传入false 表示没有收到通知
    private void button2_Click(object sender, EventArgs e)
    {

    Thread thread = new Thread(new ParameterizedThreadStart(Add));
    thread.IsBackground = true;
    thread.Start("3");
    //等待直到收到通知在往下执行
    waitHand.WaitOne();
    MessageBox.Show("Finish");
    }

    private void Add(object a)
    {
    MessageBox.Show(a.ToString());
    //通知其他线程该线程已经完成
    waitHand.Set();
    }

    #endregion

  • 相关阅读:
    高效代码审查的十个经验
    记事本
    cocos2d-x游戏引擎核心之十一——并发编程(消息通知中心)
    DE1-SOC开发板使用学习
    反思的话-180929
    反思的话-企业制度的作用180927
    XDS100V3连接Pandaboard ES OMAP4460开发板
    《手把手教你学DSP-基于TMS320F28335》书中的错误
    DSP28335做FFT傅里叶变换
    itop4412学习-上层应用多任务开发
  • 原文地址:https://www.cnblogs.com/cdaq/p/4618616.html
Copyright © 2020-2023  润新知