C# 多线程参数传递
2023-09-14 09:03:14 时间
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推荐:多线程方法调用提供参数的最好办法是将目标方法包裹在类中,并为该类定义字段,这些字段将被用作新线程的参数。
这种方法的优点是,任何时候想要启动新线程,都可以创建类的新实例,该实例带有自身的参数。
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响应时间是有限制。
多线程之常见方法使用 线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;进程是系统资源分配的单位,线程是系统调度的单位。一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;进程之间相互独立,进程之间不能共享资源,而线程共享所在进程的地址空间和其它资源。同时线程还有自己的栈和栈指针,程序计数器等寄存器。
匿名内部类方式使用多线程 在开发中,为了方便使用线程,需要随手开线程,最简单的做法就是采用匿名内部类方式使用多线程。 匿名内部类的格式: new 类名或者接口名() { 重写方法; } 本质:是该类的子类对象或者该接口的实现类对象。
相关文章
- C# winform开发界面美化
- C# 多线程使用lamda表达式编程
- C#多线程
- c#数组赋初值_C#数组初始化
- C# 多线程 ThreadStart和ParameterizedThreadStart
- c# mysql executenonquery_C#与数据库访问技术之ExecuteNonQuery方法
- C#中多线程Tread的使用案例分享
- 【C#异步】异步多线程的本质,上下文流转和同步
- 【Unity3D】Unity 中使用 C# 调用 Java ① ( Android Studio 模块准备 | 编译 Android 模块拿到字节码文件 | 拷贝字节码到 Unity 编辑器 )
- dotnet C# 基于 INotifyPropertyChanged 实现一个 CLR 属性绑定辅助类
- C#多线程的几种实现方法详解编程语言
- C#解析RAS文件SUM光栅文件图象的代码
- C#多线程Singleton(单件)模式模板
- C#利用ODP.net连接Oracle数据库的操作方法
- C#中验证sql语句是否正确(不执行语句)
- c#简单读取文本的实例方法
- C#StringReplace高效的实例方法
- C#编写的windows计算器的实例代码
- c#中多线程访问winform控件的若干问题小结
- c#判断字符是否为中文的三种方法分享(正则表达式判断)
- c#读写注册表示例分享
- c#多线程中Lock()关键字的用法小结
- c#使用多线程的几种方式示例详解
- c#多线程编程基础
- C#采用FileSystemWatcher实现监视磁盘文件变更的方法
- C#中JavaScriptSerializer帮助类用法实例
- C#中Html.RenderPartial与Html.RenderAction的区别分析
- C#微信公众号开发之接收事件推送与消息排重的方法