您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

C# 多线程参数传递

2024/2/24 13:25:51发布27次查看
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", 42); // 创建执行任务的线程,并执行 thread t = new thread(new threadstart(tc.testfunction)); t.start(); //获取返回值,通过 tc.acceptresults; }
小注:
必须注意isbackground的问题,如果isbackground为false的,则windows程序在退出的时候,不会为你自动退出该线程。也就是实际上你的应用程序未结束。
msdn推荐:多线程方法调用提供参数的最好办法是将目标方法包裹在类中,并为该类定义字段,这些字段将被用作新线程的参数。
这种方法的优点是,任何时候想要启动新线程,都可以创建类的新实例,该实例带有自身的参数。
backgroundworker 类
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 = 19; 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 = 19; 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 = 30; areaobject2.height = 40; // 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()); } } }
demo代码来自msdn:点击打开链接
参考文章:点击打开链接
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", 5); })); t1.start(); }
小注:
如果通过wcf来调用的话,应该把起线程的函数放到服务端,如果放到客户端,很容易因为wcf客户端的时间限制,造成造成主程序的莫名崩溃。
崩溃的原因主要是客户端wcf响应时间是有限制。
以上就是c# 多线程参数传递的内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product