C# 多线程参数传递
之前使用多线程的时候,基本没有遇到过参数传递的情况,最近,接连遇到需要进行参数传递的多线程的使用。每次都要重新上网查一下,太麻烦了。为了方便以后的使用,就把经常参阅的网上资料记录下来。
原文地址如下:http://blog.csdn.net/jiankunking/article/details/45932289
1、通过实体类来传递(可以传递多个参数与获取返回值),demo如下:
需要在线程中调用的函数:
namespace ThreadParameterDemo
{
public class FunctionClass
{
public static string TestFunction(string name, int age)
{
//内部处理省略
return name + " 的年龄是:" + age;
}
}
}
通过实体来来封装:
namespace ThreadParameterDemo
{
/// <summary>
/// 过渡类
/// </summary>
public class TransitionalClass
{
private string name = string.Empty;
private int age;
public string acceptResults = string.Empty;
public TransitionalClass(string name, int age)
{
this.name = name;
this.age = age;
} public void TestFunction()
{
acceptResults = FunctionClass.TestFunction(this.name, this.age);
}
}
}
调用:
private void Form1_Load(object sender, EventArgs e)
{
//实例化ThreadWithState类,为线程提供参数
TransitionalClass tc = new TransitionalClass(" Jack", );
// 创建执行任务的线程,并执行
Thread t = new Thread(new ThreadStart(tc.TestFunction));
t.Start();
//获取返回值,通过 tc.acceptResults;
}
小注:
必须注意IsBackground的问题,如果IsBackground为false的,则Windows程序在退出的时候,不会为你自动退出该线程。也就是实际上你的应用程序未结束。
MSDN推荐:多线程方法调用提供参数的最好办法是将目标方法包裹在类中,并为该类定义字段,这些字段将被用作新线程的参数。
这种方法的优点是,任何时候想要启动新线程,都可以创建类的新实例,该实例带有自身的参数。
但是,ThreadStart中的函数是没有返回值和参数的
2、异步调用中的参数和返回值
能完美解决参数和返回值的是使用异步调用的方式。异步调用和Thread相比,一个最大的劣势是不能控制其优先级。
具体代码如下:
public delegate string delegateFunction(string name,int age);//委托
delegateFunction df;
private void Form1_Load(object sender, EventArgs e)
{
//指向需要调用的方法
df = new delegateFunction(FunctionClass.TestFunction);
string name = "my name";//输入参数
int age = ;
IAsyncResult result = df.BeginInvoke(name,age, null, null);
string myResult = df.EndInvoke(result);//用于接收返回值
MessageBox.Show(myResult);
}
简化:
public Func<string, int, string> df;//委托
private void Form1_Load(object sender, EventArgs e)
{
//指向需要调用的方法
df += FunctionClass.TestFunction;
string name = "my name";//输入参数
int age = ;
IAsyncResult result = df.BeginInvoke(name, age, null, null);
string myResult = df.EndInvoke(result);//用于接收返回值
MessageBox.Show(myResult);
}
小注:
通过这种方式生成新线程是运行在后台的(background),优先级为normal
3、使用 BackgroundWorker
多线程返回值最简单方法是:使用 BackgroundWorker 组件来管理线程,在任务完成时引发事件,然后用事件处理程序处理结果。
小注:
BackgroundWorker 组件用来执行诸如数据库事务、文件下载等耗时的异步操作。
在应用程序中添加一个BackgroundWorker实例,如果用的是VS,可以从工具上直接拖到应用程序:
BackgroundWorker backgroundWorker1 = new BackgroundWorker();
为了开始在后台操作,必须调用BackgroundWorker的RunWorkerAsync()方法,当调用此方时,BackgroundWorker 通过触发DoWork 事件,开始执行后台操作,DoWork 事件的代码是在另一个线程里执行的。
当后台操作完成以后,无论是completed 还是cancelled,则RunWorkerCompleted 事件被触发,通过此方法可以将后台操作的完成结果反馈给用户。
另外,通过RunWorkerCompletedEventArgs实例的Cancelled 属性,以判断是否是Cancel操作使得后台操作终止。
具体demo如下:
using System;
using System.Windows.Forms; namespace WindowsFormsApplication1
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
} private void Form2_Load(object sender, EventArgs e)
{
//TransitionalClass tc = new TransitionalClass("xiaoming", 10);
//ThreadPool.QueueUserWorkItem(new WaitCallback(TransitionalClass.TestFunction), tc);
} private void button1_Click(object sender, EventArgs e)
{
this.TestArea2();
} private System.ComponentModel.BackgroundWorker BackgroundWorker1
= new System.ComponentModel.BackgroundWorker(); private void TestArea2()
{
InitializeBackgroundWorker(); AreaClass2 AreaObject2 = new AreaClass2();
AreaObject2.Base = ;
AreaObject2.Height = ; // Start the asynchronous operation.
BackgroundWorker1.RunWorkerAsync(AreaObject2);
} private void InitializeBackgroundWorker()
{
// Attach event handlers to the BackgroundWorker object.
BackgroundWorker1.DoWork +=
new System.ComponentModel.DoWorkEventHandler(BackgroundWorker1_DoWork);
BackgroundWorker1.RunWorkerCompleted +=
new System.ComponentModel.RunWorkerCompletedEventHandler(BackgroundWorker1_RunWorkerCompleted);
} private void BackgroundWorker1_DoWork(
object sender,
System.ComponentModel.DoWorkEventArgs e)
{
//在执行DoWork 事件时,DoWorkEventArgs 实例的Result 属性,返回值到用户;在RunWorkerCompleted 事件里,RunWorkerCompletedEventArgs 实例的Result 属性接收值;
AreaClass2 AreaObject2 = (AreaClass2)e.Argument;
// Return the value through the Result property.
e.Result = AreaObject2.CalcArea();
} private void BackgroundWorker1_RunWorkerCompleted(
object sender,
System.ComponentModel.RunWorkerCompletedEventArgs e)
{
// Access the result through the Result property.
double Area = (double)e.Result;
MessageBox.Show("The area is: " + Area.ToString());
}
}
}
4、如果没有返回值的时候,可以通过匿名函数的方式简化代码
FunctionClass类新增,测试函数如下:
public static void TestFunction2(string name, int age)
{
//内部处理省略
}
调用如下:
private void Form1_Load(object sender, EventArgs e)
{
Thread t1 = new Thread(new ThreadStart(delegate
{
FunctionClass.TestFunction2("eee", );
}));
t1.Start();
}
小注:
如果通过WCF来调用的话,应该把起线程的函数放到服务端,如果放到客户端,很容易因为WCF客户端的时间限制,造成造成主程序的莫名崩溃。
崩溃的原因主要是客户端wcf响应时间是有限制。
C# 多线程参数传递的更多相关文章
- c/c++ 多线程 参数传递
多线程 参数传递 1,值传递,拷贝一份新的给新的线程.线程1中有个int变量a,在线程1中启动线程2,参数是a的值,这时就会拷贝a,线程1和线程2不共享a. 2,引用传递,不拷贝一份新的给新的线程.线 ...
- 20160208.CCPP体系详解(0018天)
程序片段(01):main.c 内容概要:PointWithOutInit #include <stdio.h> #include <stdlib.h> //01.野指针详解: ...
- QT多线程信号和槽参数传递
写了一个这样的信号 void caculateReady( QList<QString> adds, QList<double> hotV, QList<double&g ...
- Win32 API 多线程编程——一个简单实例(含消息参数传递)
Win32 API进行程序设计具有很多优点:应用程序执行代码小,运行效率高,但是他要求程序员编写的代码较多,且需要管理所有系统提供给程序的资源,要求程序员对Windows系统内核有一定的了解,会占用程 ...
- C++并发与多线程学习笔记--参数传递详解
传递临时对象 陷阱 总结 临时对象作为线程参数 线程id的概念 临时对象构造时的抓捕 成员函数指针做线程函数 传递临时对象作为线程参数 创建的工作线程不止一个,线程根据编号来确定工作内容.每个线程都需 ...
- C#多线程之线程池篇3
在上一篇C#多线程之线程池篇2中,我们主要学习了线程池和并行度以及如何实现取消选项的相关知识.在这一篇中,我们主要学习如何使用等待句柄和超时.使用计时器和使用BackgroundWorker组件的相关 ...
- C#多线程之线程同步篇2
在上一篇C#多线程之线程同步篇1中,我们主要学习了执行基本的原子操作.使用Mutex构造以及SemaphoreSlim构造,在这一篇中我们主要学习如何使用AutoResetEvent构造.Manual ...
- C++ 11 多线程--线程管理
说到多线程编程,那么就不得不提并行和并发,多线程是实现并发(并行)的一种手段.并行是指两个或多个独立的操作同时进行.注意这里是同时进行,区别于并发,在一个时间段内执行多个操作.在单核时代,多个线程是并 ...
- java中的多线程
什么是多线程? 首先得知道什么是线程? 线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行.也可以把它理解为代码运行的上下文.所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务. ...
随机推荐
- php自带函数去除html标记
strip_tags 去掉 HTML 及 PHP 的标记. 语法: string strip_tags(string str); 传回值: 字串 函式种类: 资料处理 内容说明 本函式可去掉字串中包含 ...
- 主攻ASP.NET.4.5.1 MVC5.0之重生:政府行政网站常用友情链接跳转javascript[干货分享]
<!-----------------------------------> <script language="JavaScript" type="t ...
- bootstrap 模态框中弹出层 input不能获得焦点且不可编辑
bootstrap 模态框中弹出层 input不能获得焦点且不可编辑 问题描述:bs框架支持一层model层的情况下,在模态框中弹出了自定义的弹出层.发现自定义弹出层的输入框不能获得焦点且不可编辑. ...
- 生信基础概念之unique reads VS multi-mapping reads
unique reads:在参考组上只有一个匹配点 multi-mapping reads:在参考组上有多个匹配点 下面是tophat的一个结果案例: Reads: Input : Mapped : ...
- Python绿色版
Python 安装的时候,有个选项,是问你要安装给所有用户还是只安装给当前用户,你只要选择当前用户,就会把那些需要的 dll ,包括 msvcr90.dll 都给装到 Python 目录下,你只要把 ...
- 使用concurrent.futures和ProcessPoolExecutor来替代线程和进程
concurrent.futures和ProcessPoolExecutor这两个类实现的借口分别在不同的线程或进程中执行可调用的对象,这两个类在内部维护者一个工作线程或进程池,以及要执行的队列,这两 ...
- 查看git安装目录
有时候需要知道Git在电脑中的安装位置,这里简单介绍下: Mac平台:在命令行中输入which git, 就会显示git的安装位置了; Windows平台:打开cmd,输入where git就会显示g ...
- Spring初学之泛型依赖注入
主要讲泛型依赖注入,所以核心在java文件,配置文件中只需配置扫描包即可,如下: <?xml version="1.0" encoding="UTF-8" ...
- review23
文件的创建与删除 当使用File类创建一个文件对象后,例如 File file = new File("C:\\myletter", "letter.txt") ...
- Lucene.Net 优化索引生成,即搜索显示优化
最近发现站内搜索引擎响应速度很慢,因为刚来公司之前技术员跑了源码什么的都没留下.只好自己手动破解源代码dll查找问题所在! 这个问题代码就暂时不贴了这里只写思路 原逻辑:经过整体分析后发现之前是使用 ...