C# 多线程编程

C# 多线程编程1.如果只是启动一个新线程,不需要传入参数,不需要线程返回结果,可以直接使用ThreadStart(),Thread类接收一个ThreadStart委托或ParameterizedThreadSta

大家好,又见面了,我是你们的朋友全栈君。

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 线程负担的目的了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/155090.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • postman安装包怎么安装_数据库安装教程

    postman安装包怎么安装_数据库安装教程一、Postman背景介绍用户在开发或者调试网络程序或者是网页B/S模式的程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具。今天给大家介绍的这款网页调试工具不仅可以调试简单的css、html、脚本等简单的网页基本信息,它还可以发送几乎所有类型的HTTP请求!Postman在发送网络HTTP请求方面可以说是Chrome插件类产品中的代表产品之一。二、Postman的操作环境postman适用于不同的操作系统,PostmanMac、Windo

    2022年9月18日
    2
  • UVALive – 4621 Cav 贪心 + 分析「建议收藏」

    UVALive – 4621 Cav 贪心 + 分析

    2022年1月19日
    55
  • 服务器要删除文件访问被拒绝,删除文件提示:文件夹访问被拒绝 需要来自administrator权限执行操作…

    服务器要删除文件访问被拒绝,删除文件提示:文件夹访问被拒绝 需要来自administrator权限执行操作…有时候我们在删除一些系统重要文件,或者被保护的文件的时候,会出现对话框,提示我们您需要来自administrator权限才能对此文件夹进行更改,这是什么原因导致的?今天小编就为大家分析下解决办法。方法/步骤1、右键点击提示我们需要权限的文件夹,然后点击【属性】选项。2、进入文件夹属性界面在上方菜单栏处,找到【安全】选项,然后点击下方的高级选项。3、进入高级选项,点击上方【所有者】,然后点击下方的编…

    2025年7月9日
    2
  • 小波变换分解与重构_小波变换和小波分解

    小波变换分解与重构_小波变换和小波分解转:天津大学小波分析宗婧1015202078原理可参考:https://wenku.baidu.com/view/73439a6d5901020207409cd5.html1、单层小波分解%1.单层小波分解%读入信号loadleleccum;s=leleccum(1:4000);%通过db4小波基进行离散小波变换[cA1,cD1]=dwt(s,’d…

    2022年10月21日
    2
  • struts2讲解

    struts2讲解Struts2部分1.JavaEE软件三层结构和MVC的区别?JavaEE软件三层机构是由sun公司提供JavaEE开发规范的:Web层(表现层)、业务逻辑层、数据持久层。【其中WEB层会使用前端控制器模式】MVC是一种思想,是一种模式,将软件分为Model模型、View视图、Controller控制器。【JavaEE开发更强调三层结构,web层开发更注重MVC】Struts2就是web层开发框架,符合MVC模式;struts1、webwork、jsf、SpringMVC都是MVC…

    2025年7月22日
    3
  • 通道混合器_管道混合器结构图

    通道混合器_管道混合器结构图今天我们聊一聊通道混合器,虽然网上也有很多教程,但是大部分都是讲原理的,有些很晦涩,对于萌新们去理解这个工具并不友好。所以小修把自己总结的一些经验以及网上的理论结合在一起和大家聊一聊。通道混合器是一

    2022年8月1日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号