深入分析C# Task
作者:五维思考 发布时间:2022-10-24 12:39:00
Task的MSDN的描述如下:
【Task类的表示单个操作不会返回一个值,通常以异步方式执行。
Task对象是一种的中心思想基于任务的异步模式首次引入.NETFramework 4 中。
因为由执行工作Task对象通常以异步方式执行线程池线程上而不是以同步方式在主应用程序线程中,可以使用Status属性,并将IsCanceled, IsCompleted,和IsFaulted属性,以确定任务的状态。
大多数情况下,lambda 表达式用于指定该任务所执行的工作量。
对于返回值的操作,您使用Task类。】
1、Task的优势
ThreadPool相比Thread来说具备了很多优势,但是ThreadPool却又存在一些使用上的不方便。比如:
ThreadPool不支持线程的取消、完成、失败通知等交互性操作;
ThreadPool不支持线程执行的先后次序;
以往,如果开发者要实现上述功能,需要完成很多额外的工作,现在,FCL中提供了一个功能更强大的概念:Task。Task在线程池的基础上进行了优化,并提供了更多的API。在FCL4.0中,如果我们要编写多线程程序,Task显然已经优于传统的方式。
以下是一个简单的任务示例:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Task t = new Task(() =>
{
Console.WriteLine("任务开始工作……");
//模拟工作过程
Thread.Sleep(5000);
});
t.Start();
t.ContinueWith((task) =>
{
Console.WriteLine("任务完成,完成时候的状态为:");
Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
});
Console.ReadKey();
}
}
}
2、Task的用法
2.1、创建任务
(一)无返回值的方式
方式1:
var t1 = new Task(() => TaskMethod("Task 1"));
t1.Start();
Task.WaitAll(t1);//等待所有任务结束
注:任务的状态:
Start之前为:Created
Start之后为:WaitingToRun
方式2:
Task.Run(() => TaskMethod("Task 2"));
方式3:
Task.Factory.StartNew(() => TaskMethod("Task 3")); 直接异步的方法
//或者
var t3=Task.Factory.StartNew(() => TaskMethod("Task 3"));
Task.WaitAll(t3);//等待所有任务结束
//任务的状态:
Start之前为:Running
Start之后为:Running
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var t1 = new Task(() => TaskMethod("Task 1"));
var t2 = new Task(() => TaskMethod("Task 2"));
t2.Start();
t1.Start();
Task.WaitAll(t1, t2);
Task.Run(() => TaskMethod("Task 3"));
Task.Factory.StartNew(() => TaskMethod("Task 4"));
//标记为长时间运行任务,则任务不会使用线程池,而在单独的线程中运行。
Task.Factory.StartNew(() => TaskMethod("Task 5"), TaskCreationOptions.LongRunning);
#region 常规的使用方式
Console.WriteLine("主线程执行业务处理.");
//创建任务
Task task = new Task(() =>
{
Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作.");
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
});
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
task.Wait();
#endregion
Thread.Sleep(TimeSpan.FromSeconds(1));
Console.ReadLine();
}
static void TaskMethod(string name)
{
Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
}
}
}
async/await的实现方式:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
async static void AsyncFunction()
{
await Task.Delay(1);
Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作.");
for (int i = 0; i < 10; i++)
{
Console.WriteLine(string.Format("AsyncFunction:i={0}", i));
}
}
public static void Main()
{
Console.WriteLine("主线程执行业务处理.");
AsyncFunction();
Console.WriteLine("主线程执行其他处理");
for (int i = 0; i < 10; i++)
{
Console.WriteLine(string.Format("Main:i={0}", i));
}
Console.ReadLine();
}
}
}
(二)带返回值的方式
方式4:
Task<int> task = CreateTask("Task 1");
task.Start();
int result = task.Result;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static Task<int> CreateTask(string name)
{
return new Task<int>(() => TaskMethod(name));
}
static void Main(string[] args)
{
TaskMethod("Main Thread Task");
Task<int> task = CreateTask("Task 1");
task.Start();
int result = task.Result;
Console.WriteLine("Task 1 Result is: {0}", result);
task = CreateTask("Task 2");
//该任务会运行在主线程中
task.RunSynchronously();
result = task.Result;
Console.WriteLine("Task 2 Result is: {0}", result);
task = CreateTask("Task 3");
Console.WriteLine(task.Status);
task.Start();
while (!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
result = task.Result;
Console.WriteLine("Task 3 Result is: {0}", result);
#region 常规使用方式
//创建任务
Task<int> getsumtask = new Task<int>(() => Getsum());
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
getsumtask.Start();
Console.WriteLine("主线程执行其他处理");
//等待任务的完成执行过程。
getsumtask.Wait();
//获得任务的执行结果
Console.WriteLine("任务执行结果:{0}", getsumtask.Result.ToString());
#endregion
}
static int TaskMethod(string name)
{
Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
return 42;
}
static int Getsum()
{
int sum = 0;
Console.WriteLine("使用Task执行异步操作.");
for (int i = 0; i < 100; i++)
{
sum += i;
}
return sum;
}
}
}
async/await的实现:
using System;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
public static void Main()
{
var ret1 = AsyncGetsum();
Console.WriteLine("主线程执行其他处理");
for (int i = 1; i <= 3; i++)
Console.WriteLine("Call Main()");
int result = ret1.Result; //阻塞主线程
Console.WriteLine("任务执行结果:{0}", result);
}
async static Task<int> AsyncGetsum()
{
await Task.Delay(1);
int sum = 0;
Console.WriteLine("使用Task执行异步操作.");
for (int i = 0; i < 100; i++)
{
sum += i;
}
return sum;
}
}
}
2.2、组合任务.ContinueWith
简单Demo:
using System;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
public static void Main()
{
//创建一个任务
Task<int> task = new Task<int>(() =>
{
int sum = 0;
Console.WriteLine("使用Task执行异步操作.");
for (int i = 0; i < 100; i++)
{
sum += i;
}
return sum;
});
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
//任务完成时执行处理。
Task cwt = task.ContinueWith(t =>
{
Console.WriteLine("任务完成后的执行结果:{0}", t.Result.ToString());
});
task.Wait();
cwt.Wait();
}
}
}
任务的串行:
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
ConcurrentStack<int> stack = new ConcurrentStack<int>();
//t1先串行
var t1 = Task.Factory.StartNew(() =>
{
stack.Push(1);
stack.Push(2);
});
//t2,t3并行执行
var t2 = t1.ContinueWith(t =>
{
int result;
stack.TryPop(out result);
Console.WriteLine("Task t2 result={0},Thread id {1}", result, Thread.CurrentThread.ManagedThreadId);
});
//t2,t3并行执行
var t3 = t1.ContinueWith(t =>
{
int result;
stack.TryPop(out result);
Console.WriteLine("Task t3 result={0},Thread id {1}", result, Thread.CurrentThread.ManagedThreadId);
});
//等待t2和t3执行完
Task.WaitAll(t2, t3);
//t7串行执行
var t4 = Task.Factory.StartNew(() =>
{
Console.WriteLine("当前集合元素个数:{0},Thread id {1}", stack.Count, Thread.CurrentThread.ManagedThreadId);
});
t4.Wait();
}
}
}
子任务:
using System;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
public static void Main()
{
Task<string[]> parent = new Task<string[]>(state =>
{
Console.WriteLine(state);
string[] result = new string[2];
//创建并启动子任务
new Task(() => { result[0] = "我是子任务1。"; }, TaskCreationOptions.AttachedToParent).Start();
new Task(() => { result[1] = "我是子任务2。"; }, TaskCreationOptions.AttachedToParent).Start();
return result;
}, "我是父任务,并在我的处理过程中创建多个子任务,所有子任务完成以后我才会结束执行。");
//任务处理完成后执行的操作
parent.ContinueWith(t =>
{
Array.ForEach(t.Result, r => Console.WriteLine(r));
});
//启动父任务
parent.Start();
//等待任务结束 Wait只能等待父线程结束,没办法等到父线程的ContinueWith结束
//parent.Wait();
Console.ReadLine();
}
}
}
动态并行(TaskCreationOptions.AttachedToParent) 父任务等待所有子任务完成后 整个任务才算完成
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Node
{
public Node Left { get; set; }
public Node Right { get; set; }
public string Text { get; set; }
}
class Program
{
static Node GetNode()
{
Node root = new Node
{
Left = new Node
{
Left = new Node
{
Text = "L-L"
},
Right = new Node
{
Text = "L-R"
},
Text = "L"
},
Right = new Node
{
Left = new Node
{
Text = "R-L"
},
Right = new Node
{
Text = "R-R"
},
Text = "R"
},
Text = "Root"
};
return root;
}
static void Main(string[] args)
{
Node root = GetNode();
DisplayTree(root);
}
static void DisplayTree(Node root)
{
var task = Task.Factory.StartNew(() => DisplayNode(root),
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.Default);
task.Wait();
}
static void DisplayNode(Node current)
{
if (current.Left != null)
Task.Factory.StartNew(() => DisplayNode(current.Left),
CancellationToken.None,
TaskCreationOptions.AttachedToParent,
TaskScheduler.Default);
if (current.Right != null)
Task.Factory.StartNew(() => DisplayNode(current.Right),
CancellationToken.None,
TaskCreationOptions.AttachedToParent,
TaskScheduler.Default);
Console.WriteLine("当前节点的值为{0};处理的ThreadId={1}", current.Text, Thread.CurrentThread.ManagedThreadId);
}
}
}
2.3、取消任务 CancellationTokenSource
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
private static int TaskMethod(string name, int seconds, CancellationToken token)
{
Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
for (int i = 0; i < seconds; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(1));
if (token.IsCancellationRequested) return -1;
}
return 42 * seconds;
}
private static void Main(string[] args)
{
var cts = new CancellationTokenSource();
var longTask = new Task<int>(() => TaskMethod("Task 1", 10, cts.Token), cts.Token);
Console.WriteLine(longTask.Status);
cts.Cancel();
Console.WriteLine(longTask.Status);
Console.WriteLine("First task has been cancelled before execution");
cts = new CancellationTokenSource();
longTask = new Task<int>(() => TaskMethod("Task 2", 10, cts.Token), cts.Token);
longTask.Start();
for (int i = 0; i < 5; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine(longTask.Status);
}
cts.Cancel();
for (int i = 0; i < 5; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine(longTask.Status);
}
Console.WriteLine("A task has been completed with result {0}.", longTask.Result);
}
}
}
2.4、处理任务中的异常
单个任务:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static int TaskMethod(string name, int seconds)
{
Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(seconds));
throw new Exception("Boom!");
return 42 * seconds;
}
static void Main(string[] args)
{
try
{
Task<int> task = Task.Run(() => TaskMethod("Task 2", 2));
int result = task.GetAwaiter().GetResult();
Console.WriteLine("Result: {0}", result);
}
catch (Exception ex)
{
Console.WriteLine("Task 2 Exception caught: {0}", ex.Message);
}
Console.WriteLine("----------------------------------------------");
Console.WriteLine();
}
}
}
多个任务:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static int TaskMethod(string name, int seconds)
{
Console.WriteLine("Task {0} is running on a thread id {1}. Is thread pool thread: {2}",
name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(seconds));
throw new Exception(string.Format("Task {0} Boom!", name));
return 42 * seconds;
}
public static void Main(string[] args)
{
try
{
var t1 = new Task<int>(() => TaskMethod("Task 3", 3));
var t2 = new Task<int>(() => TaskMethod("Task 4", 2));
var complexTask = Task.WhenAll(t1, t2);
var exceptionHandler = complexTask.ContinueWith(t =>
Console.WriteLine("Result: {0}", t.Result),
TaskContinuationOptions.OnlyOnFaulted
);
t1.Start();
t2.Start();
Task.WaitAll(t1, t2);
}
catch (AggregateException ex)
{
ex.Handle(exception =>
{
Console.WriteLine(exception.Message);
return true;
});
}
}
}
}
async/await的方式:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task ThrowNotImplementedExceptionAsync()
{
throw new NotImplementedException();
}
static async Task ThrowInvalidOperationExceptionAsync()
{
throw new InvalidOperationException();
}
static async Task Normal()
{
await Fun();
}
static Task Fun()
{
return Task.Run(() =>
{
for (int i = 1; i <= 10; i++)
{
Console.WriteLine("i={0}", i);
Thread.Sleep(200);
}
});
}
static async Task ObserveOneExceptionAsync()
{
var task1 = ThrowNotImplementedExceptionAsync();
var task2 = ThrowInvalidOperationExceptionAsync();
var task3 = Normal();
try
{
//异步的方式
Task allTasks = Task.WhenAll(task1, task2, task3);
await allTasks;
//同步的方式
//Task.WaitAll(task1, task2, task3);
}
catch (NotImplementedException ex)
{
Console.WriteLine("task1 任务报错!");
}
catch (InvalidOperationException ex)
{
Console.WriteLine("task2 任务报错!");
}
catch (Exception ex)
{
Console.WriteLine("任务报错!");
}
}
public static void Main()
{
Task task = ObserveOneExceptionAsync();
Console.WriteLine("主线程继续运行........");
task.Wait();
}
}
}
2.5、Task.FromResult的应用
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static IDictionary<string, string> cache = new Dictionary<string, string>()
{
{"0001","A"},
{"0002","B"},
{"0003","C"},
{"0004","D"},
{"0005","E"},
{"0006","F"},
};
public static void Main()
{
Task<string> task = GetValueFromCache("0006");
Console.WriteLine("主程序继续执行。。。。");
string result = task.Result;
Console.WriteLine("result={0}", result);
}
private static Task<string> GetValueFromCache(string key)
{
Console.WriteLine("GetValueFromCache开始执行。。。。");
string result = string.Empty;
//Task.Delay(5000);
Thread.Sleep(5000);
Console.WriteLine("GetValueFromCache继续执行。。。。");
if (cache.TryGetValue(key, out result))
{
return Task.FromResult(result);
}
return Task.FromResult("");
}
}
}
2.6、使用IProgress实现异步编程的进程通知
IProgress<in T>只提供了一个方法void Report(T value),通过Report方法把一个T类型的值报告给IProgress,然后IProgress<in T>的实现类Progress<in T>的构造函数接收类型为Action<T>的形参,通过这个委托让进度显示在UI界面中。
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static void DoProcessing(IProgress<int> progress)
{
for (int i = 0; i <= 100; ++i)
{
Thread.Sleep(100);
if (progress != null)
{
progress.Report(i);
}
}
}
static async Task Display()
{
//当前线程
var progress = new Progress<int>(percent =>
{
Console.Clear();
Console.Write("{0}%", percent);
});
//线程池线程
await Task.Run(() => DoProcessing(progress));
Console.WriteLine("");
Console.WriteLine("结束");
}
public static void Main()
{
Task task = Display();
task.Wait();
}
}
}
2.7、Factory.FromAsync的应用 (简APM模式(委托)转换为任务)(BeginXXX和EndXXX)
带回调方式的
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
private delegate string AsynchronousTask(string threadName);
private static string Test(string threadName)
{
Console.WriteLine("Starting...");
Console.WriteLine("Is thread pool thread: {0}", Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
Thread.CurrentThread.Name = threadName;
return string.Format("Thread name: {0}", Thread.CurrentThread.Name);
}
private static void Callback(IAsyncResult ar)
{
Console.WriteLine("Starting a callback...");
Console.WriteLine("State passed to a callbak: {0}", ar.AsyncState);
Console.WriteLine("Is thread pool thread: {0}", Thread.CurrentThread.IsThreadPoolThread);
Console.WriteLine("Thread pool worker thread id: {0}", Thread.CurrentThread.ManagedThreadId);
}
//执行的流程是 先执行Test--->Callback--->task.ContinueWith
static void Main(string[] args)
{
AsynchronousTask d = Test;
Console.WriteLine("Option 1");
Task<string> task = Task<string>.Factory.FromAsync(
d.BeginInvoke("AsyncTaskThread", Callback, "a delegate asynchronous call"), d.EndInvoke);
task.ContinueWith(t => Console.WriteLine("Callback is finished, now running a continuation! Result: {0}",
t.Result));
while (!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
}
}
}
不带回调方式的
using System;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
private delegate string AsynchronousTask(string threadName);
private static string Test(string threadName)
{
Console.WriteLine("Starting...");
Console.WriteLine("Is thread pool thread: {0}", Thread.CurrentThread.IsThreadPoolThread);
Thread.Sleep(TimeSpan.FromSeconds(2));
Thread.CurrentThread.Name = threadName;
return string.Format("Thread name: {0}", Thread.CurrentThread.Name);
}
//执行的流程是 先执行Test--->task.ContinueWith
static void Main(string[] args)
{
AsynchronousTask d = Test;
Task<string> task = Task<string>.Factory.FromAsync(
d.BeginInvoke, d.EndInvoke, "AsyncTaskThread", "a delegate asynchronous call");
task.ContinueWith(t => Console.WriteLine("Task is completed, now running a continuation! Result: {0}",
t.Result));
while (!task.IsCompleted)
{
Console.WriteLine(task.Status);
Thread.Sleep(TimeSpan.FromSeconds(0.5));
}
Console.WriteLine(task.Status);
}
}
}
//Task启动带参数和返回值的函数任务
//下面的例子test2 是个带参数和返回值的函数。
private int test2(object i)
{
this.Invoke(new Action(() =>
{
pictureBox1.Visible = true;
}));
System.Threading.Thread.Sleep(3000);
MessageBox.Show("hello:" + i);
this.Invoke(new Action(() =>
{
pictureBox1.Visible = false;
}));
return 0;
}
//测试调用
private void call()
{
//Func<string, string> funcOne = delegate(string s){ return "fff"; };
object i = 55;
var t = Task<int>.Factory.StartNew(new Func<object, int>(test2), i);
}
//= 下载网站源文件例子 == == == == == == == == == == == ==
//HttpClient 引用System.Net.Http
private async Task< int> test2(object i)
{
this.Invoke(new Action(() =>
{
pictureBox1.Visible = true;
}));
HttpClient client = new HttpClient();
var a = await client.GetAsync("http://www.baidu.com");
Task<string> s = a.Content.ReadAsStringAsync();
MessageBox.Show (s.Result);
//System.Threading.Thread.Sleep(3000);
//MessageBox.Show("hello:"+ i);
this.Invoke(new Action(() =>
{
pictureBox1.Visible = false;
}));
return 0;
}
async private void call()
{
//Func<string, string> funcOne = delegate(string s){ return "fff"; };
object i = 55;
var t = Task<Task<int>>.Factory.StartNew(new Func<object, Task<int>>(test2), i);
}
//----------或者----------
private async void test2()
{
this.Invoke(new Action(() =>
{
pictureBox1.Visible = true;
}));
HttpClient client = new HttpClient();
var a = await client.GetAsync("http://www.baidu.com");
Task<string> s = a.Content.ReadAsStringAsync();
MessageBox.Show (s.Result);
this.Invoke(new Action(() =>
{
pictureBox1.Visible = false;
}));
}
private void call()
{
var t = Task.Run(new Action(test2));
//相当于
//Thread th= new Thread(new ThreadStart(test2));
//th.Start();
}
Task启动带参数和返回值的函数任务
来源:https://www.cnblogs.com/zhaoshujie/p/11082753.html


猜你喜欢
- 方式1:1. 明确 Spark中Job 与 Streaming中 Job 的区别1.1 Spark Core一个 RDD DAG Graph
- 在做Android支付的时候肯定会用到支付宝支付, 根据官方给出的demo做起来非常费劲,所以我们需要一次简单的封装。 封装的代码也很简单,
- 有时安全不得不考虑,看看新闻泄漏风波事件就知道了我们在用Spring boot进行开发时,经常要配置很多外置参数ftp、数据库连接信息、支付
- @Profiles和@PropertySource根据环境切换配置文件使用@PropertySource注解加载配置文件,并制定解析配置文件
- 本文实例讲述了C#自定义RSA加密解密及RSA签名和验证类。分享给大家供大家参考。具体分析如下:这个C#类自定义RSA加密解密及RSA签名和
- Servlet:当然,在servlet中,一般跳转都发生在doGet, doPost等方法里面。1) redirect 方式response
- 方法一:Hashtable ht = new Hashtable();  
- 之前已经为大家介绍过利用Java实现带GUI的气泡诗词特效,本文将为大家介绍另一种方法同样也可以实现气泡诗词的效果。下面是示例代码impor
- 在Android中偶尔会用到开关,Switch就是一个简单易使用的不错的控件。首先,在布局中添加上Switch控件:<Switch &
- 本教程源码https://github.com/bestaone/HiAuth源码比较全面,教程我就只介绍关键代码了,喜欢的点个star,谢
- 1.客户端代码public class UploadPicClient { public static void main(String[]
- 如下所示:package java.util;public interface Enumeration<E> { boolean
- 声明式事务回顾事务事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎!事务管理是企业级应用程序开发中必备技术,用来确保数据的完整
- springboot+mybatis报错找不到实体类找不到实体类的错误可能有很多,接下来列举几个地方启动类位置不对,启动类应该在你的serv
- 前言在上一篇文章中讲完了SpringMVC的大部分知识,此篇文章中主要讲解 * 。上一篇文章🚩 * 的使用是非常普遍的。例如在 OA系统中通
- 1. 多行编辑先来体验一下从xml文件拷贝字段新建实体对象一般我们为了新建多表连接后映射的 ResultMap ,耗费不少时间,那么我们就来
- 1 实战前的理论基础1.1 Spring Batch是什么Spring Batch 是一个轻量级、全面的批处理框架,旨在支持开发对企业系统日
- 传统的多分支方式(圈复杂度为6):public String order(String type) { if ("1&
- 1.剖析异或运算(^) 二元 ^ 运算符是为整型和 bool 类型预定义的。对于整型,^ 将计算操作数的按位“异或”。对于 bool 操作数
- 本文实例讲述了C#生成二维码的方法。分享给大家供大家参考。具体实现方法如下:首先引用ThoughtWorks.QRCode.dll具体代码如