一、开启多线程-new Thread的使用
示例一
Thread thread25yi = new Thread(new ThreadStart(obj.MethodTimer1));
thread25yi.Start();
void MethodTimer1()
{
while (true)
{
Console.WriteLine(DateTime.Now.ToString() + "_" + thread25yi.CurrentThread.ManagedThreadId.ToString());
thread25yi.CurrentThread.Join(100);//阻止设定时间
}
}
示例二
Thread thread = new Thread((s) =>
{
//你的代码
Socket serSocket = (Socket)s;
};
//获取或设置一个值,该值指示某个线程是否为后台线程。
thread.IsBackground = true;
//参数:寻址方式 传输数据方式 通信协议
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//开启线程并传参
//导致操作系统将当前实例的状态更改为 System.Threading.ThreadState.Running,并选择提供包含线程执行的方法要使用的数据的对象。
thread.Start(socket);//开启并传参
二、开启多线程- Task.Run的使用
示例一:语法代码
Task.Run(() =>
{
try
{
//你的代码
}
catch (Exception e)
{
//你的代码
}
}
示例二:完整示例代码
程序环境:
程序:WindowsForms(windows窗体)
FW版本:.NET Framework 4.5
代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsAccess_Shift_MSServer
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Task.Run(()=> {
this.GetData();
});
}
private delegate void richTextBoxCallBack();
private void GetData() {
for (int i = 0; i < 99; i++)
{
richTextBoxCallBack richTextBoxCallBack = delegate () {
SucceedRichTextBox.AppendText(i + "_行\n");
};
SucceedRichTextBox.Invoke(richTextBoxCallBack);
Thread.Sleep(2000);
}
}
private void label1_Click(object sender, EventArgs e)
{
}
}
}
三、开启子线程后,想调用父线程的方法
这里会有个错误提示,如下:
线程间操作无效: 从不是创建控件的线程访问它
解决办法:C# 线程间操作无效: 从不是创建控件的线程访问它--多线程操作-CSDN博客
延伸阅读
内容来自:总结C#多线程(Thread和Task)_c# task thread-CSDN博客
线程(Thread)是进程中的基本执行单元,是操作系统分配CPU时间的基本单位,一个进程可以包含若干个线程,在进程入口执行的第一个线程被视为这个进程的主线程。以下内容介绍C# Thread和Task实现多线程。
1、C# 线程介绍
进程作为操作系统执行程序的基本单位,拥有应用程序的资源,进程包含线程,进程的资源被线程共享,线程不拥有资源。通过Thread类新建线程默认为前台线程。当所有前台线程关闭时,所有的后台线程也会被直接终止,不会抛出异常。由于线程的执行顺序和程序的执行情况不可预知,所以使用挂起和唤醒容易发生死锁的情况,在实际应用中应该尽量少用。
使用线程的作用:
1)可以使用线程将代码同其他代码隔离,提高应用程序的可靠性。
2)可以使用线程来简化编码。
3)可以使用线程来实现并发执行。
2、线程的使用
C# 中多线程的使用可以通过System.Threading.Thread 实现,也可以通过System.Threading.Tasks.Task实现.
System.Threading.Thread 类用于线程的工作。它允许创建并访问多线程应用程序中的单个线程。进程中第一个被执行的线程称为主线程。
当 C# 程序开始执行时,主线程自动创建。使用 Thread 类创建的线程被主线程的子线程调用。可以使用 Thread 类的 CurrentThread 属性访问线程。Task是.NET4.0加入的,与线程池ThreadPool的功能类似,用Task开启新任务时,会从线程池中调用线程,而Thread每次实例化都会创建一个新的线程。我们可以说Task是一种基于任务的编程模型。它与Thread的主要区别是,更加方便对线程进程调度和获取线程的执行结果。并且Task是针对多核有优化。
2.1使用Thread
using System;
using System.Threading;
//简单的线程场景:启动一个静态方法运行
//第二个线程。
public class ThreadExample
{
//线程启动时调用ThreadProc方法。
//它循环10次,写入控制台和屈服
//每个时间片的剩余部分,然后结束。
public static void ThreadProc()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("ThreadProc: {0}", i);
//生成剩余的时间片。
Thread.Sleep(0);
}
}
public static void Main()
{
Console.WriteLine("主线程:启动第二个线程。");
//线程类的构造函数需要一个ThreadStart
//对象上要执行的方法的线程。
//c#简化了这个委托的创建。
Thread t = new Thread(new ThreadStart(ThreadProc));
// 开始ThreadProc。请注意,在单处理器上,新的
//线程没有得到任何处理器时间,直到主线程
//被抢占或产生。取消线程。睡眠
//使用t.Start()来查看区别。
//可以通过提供委托来启动线程,该委托表示线程在其类构造函数中执行的方法。 然后调用 Start 方法开始执行。
t.Start();
//Thread.Sleep(0);
for (int i = 0; i < 4; i++)
{
Console.WriteLine("主线程: 执行方法。");
Thread.Sleep(0);
}
Console.WriteLine("主线程:调用Join(),等待线程进程结束。");
t.Join();
Console.WriteLine("主线程:ThreadProc。加入已恢复。按“Enter”结束程序。");
Console.ReadLine();
}
}
注意:进程启动时,公共语言运行时将自动创建单个前台线程以执行应用程序代码。 除了此主前台线程,进程还可以创建一个或多个线程来执行与进程关联的程序代码的一部分。 这些线程可以在前台或后台执行。 此外,还可以使用 ThreadPool 类来执行由公共语言运行时管理的工作线程上的代码。
2.2使用Task
下面的示例创建并执行四个任务。 三个任务执行 Action<T>
名为的委托 action ,该委托接受类型的参数 Object
。 第四个任务执行 lambda 表达式 (Action
委托) ,该委托在对任务创建方法的调用中以内联方式定义。 每个任务实例化并以不同的方式运行:
例如:
using System;
using System.Threading;
using System.Threading.Tasks;
class Example
{
static void Main()
{
Action<object> action = (object obj) =>
{
Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, obj,
Thread.CurrentThread.ManagedThreadId);
};
// 创建一个任务但不启动它。
Task t1 = new Task(action, "alpha");
// 构造一个已启动的任务
Task t2 = Task.Factory.StartNew(action, "beta");
// 阻塞主线程以演示t2正在执行
t2.Wait();
// 启动 t1
t1.Start();
Console.WriteLine("t1 has been launched. (Main Thread={0})",
Thread.CurrentThread.ManagedThreadId);
// 等待任务完成。
t1.Wait();
// 使用Task.Run构造一个已启动的任务。
String taskData = "delta";
Task t3 = Task.Run(() => {
Console.WriteLine("Task={0}, obj={1}, Thread={2}",
Task.CurrentId, taskData,
Thread.CurrentThread.ManagedThreadId);
});
// 等待任务完成。
t3.Wait();
// 构造一个未启动的任务
Task t4 = new Task(action, "gamma");
// 同步运行它
t4.RunSynchronously();
//虽然任务是同步运行的,但这是一个很好的实践
//在任务抛出异常时等待它。
t4.Wait();
}
}
Task
可以通过多种方式创建实例。 从 .NET Framework 4.5 开始,最常见的方法是调用静态Run
方法。 Run方法提供了一种简单的方法来使用默认值启动任务,而无需其他参数。
例如
using System;
using System.Threading.Tasks;
public class Example
{
public static async Task Main()
{
await Task.Run( () => {
int ctr = 0;
for (ctr = 0; ctr <= 1000000; ctr++)
{}
Console.WriteLine("Finished {0} loop iterations",
ctr);
} );
}
}
.NET Framework 4 中启动任务的最常见方法,是静态 TaskFactory.StartNew 方法。 Task.Factory属性返回 TaskFactory 对象。 方法的重载 TaskFactory.StartNew 使你可以指定要传递给任务创建选项和任务计划程序的参数。
例如
using System;
using System.Threading.Tasks;
public class Example
{
public static void Main()
{
Task t = Task.Factory.StartNew( () => {
int ctr = 0;
for (ctr = 0; ctr <= 1000000; ctr++)
{}
Console.WriteLine("Finished {0} loop iterations",
ctr);
} );
t.Wait();
}
}
3、Thread和Task常用属性和方法
更多请阅读原文:
总结C#多线程(Thread和Task)_c# task thread-CSDN博客