zoukankan      html  css  js  c++  java
  • C# 多线程编程

    1.如果只是启动一个新线程,不需要传入参数,不需要线程返回结果,可以直接使用ThreadStart(),

    Thread类接收一个ThreadStart委托或ParameterizedThreadStart委托的构造函数。ThreadStart委托中  作为参数的方法   不需要参数,并且没有返回值。ParameterizedThreadStart委托,可以在线程start的时候,传入参数,利用这个参数可以向线程传递参数(ParameterizedThreadStart是一个有参的、返回值为void的委托,参数类型必须是object)。

    private void btOnlineLogin_Click(object sender, EventArgs e) 
        {
            Thread CheckStatusThread = new Thread(new ThreadStart(CheckStatus));       
         CheckStatusThread.Start(); //无参和返回值的多线程 
      }

    private void CheckStatus()
    {
      //do some thing here
    }

    2. 如果需要向线程传入参数,但不需要线程返回值,用ParameterizedThreadStart是一个有参的、返回值为void的委托,参数类型必须是object,且只能有一个object参数传入,
    如果要传入多个参数,可以用下面3中的Func()或者定义一个结构体,结构体包含你要传入的参数,然后把结构体当作object传入。

    private void btOnlineLogin_Click(object sender, EventArgs e) 
    {
            Thread CheckStatusThread = new Thread(new ParameterizedThreadStart(CheckStatus));       
        CheckStatusThread.Start("print me"); //有传入参,无返回值的多线程 
    }

    private void CheckStatus(object value)
    {
      Console.WriteLine(value)
    }
    //==============================总之上述用Thread方式,都没有返回值。

    3.如果新线程不需要传入参数,但是需要得到返回结果,可以有两种做法:

    a: 定义一个全局变量,按照上述1中方法启动一个无参无函数返回值的线程,将要返回的结果设置给全局变量

      public class Class1
      {
        bool Ready= false;
        private void btOnlineLogin_Click(object sender, EventArgs e)
        {
          Thread CheckStatusThread = new Thread(new ThreadStart(CheckStatus));
          CheckStatusThread.Start(); //无参和返回值的多线程

          while(!Ready)
          {
            Console.WriteLine("wait for status to ready");
          }

        }

        private void CheckStationLockedWindow()
        {
          System.Threading.Thread.Sleep(1000); //使 UI 线程有了处理界面消息的机会
          Ready = true;
        }

      }

    b.使用Func(in_param_type, in_param_type, out_param_type), 然后使用Func的BeginInvoke() 异步启动一个新线程,该做法界面会卡住。

    private void button33_Click(object sender, EventArgs e)
    {
      Func<bool> test = MyTestMethod;
      // Func<bool> test = new Func<bool>(MyTestMethod); //这样一样
      IAsyncResult result = test.BeginInvoke(null, null); //不用传入参数
      bool fin = test.EndInvoke(result);
      if(fin)
      {
        Console.WriteLine("OK.........");
      }

    }

    private bool WaitAndCreateEmptyFwFolder()
    {
      Stopwatch timer = new Stopwatch();
      timer.Reset();
      timer.Start();
      while(timer.ElapsedMilliseconds <20*1000)
      {

        System.Threading.Thread.Sleep(1000); //使 UI 线程有处理界面消息的机会,防止卡住

        Application.DoEvents();

        Console.WriteLine("Elappsed time:" + timer.ElapsedMilliseconds.ToString());
      }
      return true;
    }

    3. 如果即需要给线程传入参数还需要得到线程返回值,还是可以用Func(), 用Func() 可以不用定义自己的delegate了。

    public class Class1
    { 
       private void button33_Click(object sender, EventArgs e)
      {
        Func<string, bool> test = PrintSomeThing;
        IAsyncResult result = test.BeginInvoke("Print me", null, null);
        bool fin = test.EndInvoke(result);

    if (fin)
    {
    Console.WriteLine("OK.........");
    }

      }

      private bool PrintSomeThing(string arg)

      {

    Stopwatch timer = new Stopwatch();
    timer.Reset();
    timer.Start();
    while (timer.ElapsedMilliseconds < 10 * 1000)
    {

      System.Threading.Thread.Sleep(1000); //使 UI 线程有处理界面消息的机会

        Application.DoEvents();
        Console.WriteLine(arg);
      }
    return true;

    }

    }

    4. 第四种多线程用task:System.Thread.Tasks.Task

    Task的参数有两种,一种是Action(无返回值),一种是Func。

    public class Class1

    {

       private void button33_Click(object sender, EventArgs e)

         {

    //==============带有返回值和传入参数的
    //Task task  = Task<bool>.Factory.StartNew(new Func<object,bool>(TaskMthod),"321");   //带有返回值和传入参数的
    Task<bool> task = new Task<bool>(TaskMthodWithReturnAndInParam, "123");   //new Task<>()中的<>里面放返回值类型,
                                         //()里面放Func类型method名字。
                                         // 如果直接用new Task()没有<>则没有返回值,里面放Action类型method名字。

    task.Start();//start async          

    //Console.WriteLine(task.Result.ToString()); //task.Result will block the thread unitil the task is done and run to next step, UI will stuck
    //task.Wait(); //will block until done
        while(!task.IsCompleted) // this won't block UI
              {
                    Application.DoEvents();
              }
              Console.WriteLine(task.Result.ToString());
    //================只有返回值,无传入参数的
    Task<bool> task2 = new Task<bool>(TaskMthodWithReturnNoInParam);          
    task2.Start();//start async
       while(!task2.IsCompleted)
              {
                    Application.DoEvents();
              }
    Console.WriteLine(task2.Result.ToString());
    
    //Task.WaitAll(task1,task2); //wait all task done

    //===================没有返回值,只有传入参数的
    Task task = Task.Run(() => TaskMthodWithInParamOnly(true, true));          
    while (!task.IsCompleted)          
    {              
    Application.DoEvents();          
    }

    }
    private void TaskMthodWithInParamOnly(bool val1, bool val2)
    {
        Stopwatch timer = new Stopwatch();
        timer.Reset();
        timer.Start();
        while (timer.ElapsedMilliseconds < 20 * 1000)
        {
            Console.WriteLine("Elappsed time:" + timer.ElapsedMilliseconds.ToString());
        }
    }
    private bool TaskMthodWithReturnNoInParam()
    {
          Stopwatch timer = new Stopwatch();
          timer.Reset();
          timer.Start();
          while (timer.ElapsedMilliseconds < 20 * 1000)
          {
              Console.WriteLine("Elappsed time:" + timer.ElapsedMilliseconds.ToString());
          }
          return true;
    }
     
    private bool TaskMthodWithReturnAndInParam(object val)
    {
          Stopwatch timer = new Stopwatch();
          timer.Reset();
          timer.Start();
          while (timer.ElapsedMilliseconds < 20 * 1000)
          {
              Console.WriteLine(val.ToString());
          }
          return true;
    }
    }

    如下内容引自https://www.cnblogs.com/liuqiyun/p/8110058.html

    BeginInvoke 方法所调用的委托无论如何都是在 UI 线程中执行的。
    那 BeginInvoke 究竟有什么用呢?
    在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,具体的原因可以在看完我的这篇之后看看这篇:在多线程中如何调用Winform,如果你是大牛的话就不要看我这篇了,直接看那篇吧,反正那篇文章我没怎么看懂。
    Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界面显示。
    正确的做法是将工作线程中涉及更新界面的代码封装为一个方法,通过 Invoke 或者 BeginInvoke 去调用,两者的区别就是一个导致工作线程等待,而另外一个则不会。
    而所谓的“一面响应操作,一面添加节点”永远只能是相对的,使 UI 线程的负担不至于太大而以,因为界面的正确更新始终要通过 UI 线程去做,我们要做的事情是在工作线程中包揽大部分的运算,而将对纯粹的界面更新放到 UI 线程中去做,这样也就达到了减轻 UI 线程负担的目的了。

  • 相关阅读:
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    Security and Cryptography in Python
    基于分布式锁解决定时任务重复问题
    基于Redis的Setnx实现分布式锁
    基于数据库悲观锁的分布式锁
    使用锁解决电商中的超卖
  • 原文地址:https://www.cnblogs.com/keeprealblog/p/12804038.html
Copyright © 2011-2022 走看看