关键词搜索

源码搜索 ×
×

C# 多线程参数传递

发布2015-05-23浏览6576次

详情内容

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

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

  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. }
通过实体来来封装:
  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. public void TestFunction()
  17. {
  18. acceptResults = FunctionClass.TestFunction(this.name, this.age);
  19. }
  20. }
  21. }
调用:

  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相比,一个最大的劣势是不能控制其优先级。 

具体代码如下:

  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, null, null);
  10. string myResult = df.EndInvoke(result);//用于接收返回值
  11. MessageBox.Show(myResult);
  12. }
简化:

  1. public Func<string, int, string> 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, null, null);
  9. string myResult = df.EndInvoke(result);//用于接收返回值
  10. MessageBox.Show(myResult);
  11. }

小注:

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


3、使用 BackgroundWorker

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

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

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

具体demo如下:

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

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

参考文章:点击打开链接

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

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

  1. public static void TestFunction2(string name, int age)
  2. {
  3. //内部处理省略
  4. }
调用如下:

  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响应时间是有限制。

相关技术文章

最新源码

下载排行榜

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载