C# 多线程参数传递

1、通过实体类来传递(可以传递多个参数与获取返回值),demo如下:

需要在线程中调用的函数:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. namespace ThreadParameterDemo  
  2. {  
  3.     public class FunctionClass  
  4.     {  
  5.         public static string TestFunction(string name, int age)  
  6.         {  
  7.             //内部处理省略  
  8.             return name + " 的年龄是:" + age;  
  9.         }  
  10.     }  
  11. }  
通过实体来来封装:
[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. namespace ThreadParameterDemo  
  2. {  
  3.     /// <summary>  
  4.     /// 过渡类  
  5.     /// </summary>  
  6.     public class TransitionalClass  
  7.     {  
  8.         private string name = string.Empty;  
  9.         private int age;  
  10.         public string acceptResults = string.Empty;  
  11.         public TransitionalClass(string name, int age)  
  12.         {  
  13.             this.name = name;  
  14.             this.age = age;  
  15.         }  
  16.   
  17.         public void TestFunction()  
  18.         {  
  19.             acceptResults = FunctionClass.TestFunction(this.name, this.age);  
  20.         }  
  21.     }  
  22. }  
调用:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void Form1_Load(object sender, EventArgs e)  
  2.       {  
  3.           //实例化ThreadWithState类,为线程提供参数    
  4.           TransitionalClass tc = new TransitionalClass(" Jack", 42);  
  5.           // 创建执行任务的线程,并执行    
  6.           Thread t = new Thread(new ThreadStart(tc.TestFunction));  
  7.           t.Start();  
  8.           //获取返回值,通过 tc.acceptResults;    
  9.       }  

小注:

必须注意IsBackground的问题,如果IsBackground为false的,则Windows程序在退出的时候,不会为你自动退出该线程。也就是实际上你的应用程序未结束。

MSDN推荐:多线程方法调用提供参数的最好办法是将目标方法包裹在类中,并为该类定义字段,这些字段将被用作新线程的参数。 

这种方法的优点是,任何时候想要启动新线程,都可以创建类的新实例,该实例带有自身的参数。

        BackgroundWorker 类

ThreadStart中的函数是没有返回值和参数的

2、异步调用中的参数和返回值
能完美解决参数和返回值的是使用异步调用的方式。异步调用和Thread相比,一个最大的劣势是不能控制其优先级。 

具体代码如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public delegate string delegateFunction(string name,int age);//委托  
  2. delegateFunction df;  
  3. private void Form1_Load(object sender, EventArgs e)  
  4. {  
  5.     //指向需要调用的方法  
  6.     df = new delegateFunction(FunctionClass.TestFunction);  
  7.     string name = "my name";//输入参数   
  8.     int age = 19;  
  9.     IAsyncResult result = df.BeginInvoke(name,age, nullnull);  
  10.     string myResult = df.EndInvoke(result);//用于接收返回值   
  11.     MessageBox.Show(myResult);  
  12. }  
简化:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public Func<stringintstring>  df;//委托  
  2.        private void Form1_Load(object sender, EventArgs e)  
  3.        {  
  4.            //指向需要调用的方法  
  5.            df += FunctionClass.TestFunction;  
  6.            string name = "my name";//输入参数   
  7.            int age = 19;  
  8.            IAsyncResult result = df.BeginInvoke(name, age, nullnull);  
  9.            string myResult = df.EndInvoke(result);//用于接收返回值   
  10.            MessageBox.Show(myResult);  
  11.        }  

小注:

通过这种方式生成新线程是运行在后台的(background),优先级为normal


3、使用 BackgroundWorker

多线程返回值最简单方法是:使用 BackgroundWorker 组件来管理线程,在任务完成时引发事件,然后用事件处理程序处理结果。

小注:
BackgroundWorker 组件用来执行诸如数据库事务、文件下载等耗时的异步操作。
在应用程序中添加一个BackgroundWorker实例,如果用的是VS,可以从工具上直接拖到应用程序:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. BackgroundWorker backgroundWorker1 = new BackgroundWorker();  
       为了开始在后台操作,必须调用BackgroundWorker的RunWorkerAsync()方法,当调用此方时,BackgroundWorker 通过触发DoWork 事件,开始执行后台操作,DoWork 事件的代码是在另一个线程里执行的。
       当后台操作完成以后,无论是completed 还是cancelled,则RunWorkerCompleted 事件被触发,通过此方法可以将后台操作的完成结果反馈给用户。
       另外,通过RunWorkerCompletedEventArgs实例的Cancelled 属性,以判断是否是Cancel操作使得后台操作终止。

具体demo如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. using System;  
  2. using System.Windows.Forms;  
  3.   
  4. namespace WindowsFormsApplication1  
  5. {  
  6.     public partial class Form2 : Form  
  7.     {  
  8.         public Form2()  
  9.         {  
  10.             InitializeComponent();  
  11.         }  
  12.   
  13.         private void Form2_Load(object sender, EventArgs e)  
  14.         {  
  15.             //TransitionalClass tc = new TransitionalClass("xiaoming", 10);  
  16.             //ThreadPool.QueueUserWorkItem(new WaitCallback(TransitionalClass.TestFunction), tc);  
  17.         }  
  18.   
  19.         private void button1_Click(object sender, EventArgs e)  
  20.         {  
  21.             this.TestArea2();  
  22.         }  
  23.   
  24.         private System.ComponentModel.BackgroundWorker BackgroundWorker1  
  25.     = new System.ComponentModel.BackgroundWorker();  
  26.   
  27.         private void TestArea2()  
  28.         {  
  29.             InitializeBackgroundWorker();  
  30.   
  31.             AreaClass2 AreaObject2 = new AreaClass2();  
  32.             AreaObject2.Base = 30;  
  33.             AreaObject2.Height = 40;  
  34.   
  35.             // Start the asynchronous operation.  
  36.             BackgroundWorker1.RunWorkerAsync(AreaObject2);  
  37.         }  
  38.   
  39.         private void InitializeBackgroundWorker()  
  40.         {  
  41.             // Attach event handlers to the BackgroundWorker object.  
  42.             BackgroundWorker1.DoWork +=  
  43.                 new System.ComponentModel.DoWorkEventHandler(BackgroundWorker1_DoWork);  
  44.             BackgroundWorker1.RunWorkerCompleted +=  
  45.                 new System.ComponentModel.RunWorkerCompletedEventHandler(BackgroundWorker1_RunWorkerCompleted);  
  46.         }  
  47.   
  48.         private void BackgroundWorker1_DoWork(  
  49.             object sender,  
  50.             System.ComponentModel.DoWorkEventArgs e)  
  51.         {  
  52.             //在执行DoWork 事件时,DoWorkEventArgs 实例的Result 属性,返回值到用户;在RunWorkerCompleted 事件里,RunWorkerCompletedEventArgs 实例的Result 属性接收值;  
  53.             AreaClass2 AreaObject2 = (AreaClass2)e.Argument;  
  54.             // Return the value through the Result property.  
  55.             e.Result = AreaObject2.CalcArea();  
  56.         }  
  57.   
  58.         private void BackgroundWorker1_RunWorkerCompleted(  
  59.             object sender,  
  60.             System.ComponentModel.RunWorkerCompletedEventArgs e)  
  61.         {  
  62.             // Access the result through the Result property.   
  63.             double Area = (double)e.Result;  
  64.             MessageBox.Show("The area is: " + Area.ToString());  
  65.         }  
  66.     }  
  67. }  

demo代码来自MSDN: 点击打开链接

参考文章:点击打开链接

4、如果不如返回值的时候,应该怎么优雅的写呢?匿名函数啊偷笑

FunctionClass类新增,测试函数如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public static void TestFunction2(string name, int age)  
  2.      {  
  3.          //内部处理省略              
  4.      }  
调用如下:

[csharp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. private void Form1_Load(object sender, EventArgs e)  
  2.        {  
  3.            Thread t1 = new Thread(new ThreadStart(delegate  
  4.            {  
  5.                FunctionClass.TestFunction2("eee", 5);  
  6.            }));  
  7.            t1.Start();            
  8.        }  

小注:

如果通过WCF来调用的话,应该把起线程的函数放到服务端,如果放到客户端,很容易因为WCF客户端的时间限制,造成造成主程序的莫名崩溃。

崩溃的原因主要是客户端wcf响应时间是有限制。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值