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();
});
t.Start();
t.ContinueWith((task) =>
{
Console.WriteLine("任务完成,完成时候的状态为:");
Console.WriteLine("IsCanceled={0}\tIsCompleted={1}\tIsFaulted={2}", task.IsCanceled, task.IsCompleted, task.IsFaulted);
});
Console.ReadKey();
}
}
} Program
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 = ; i < ; i++)
{
Console.WriteLine(i);
}
});
//启动任务,并安排到当前任务队列线程中执行任务(System.Threading.Tasks.TaskScheduler)
task.Start();
Console.WriteLine("主线程执行其他处理");
task.Wait();
#endregion Thread.Sleep(TimeSpan.FromSeconds());
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);
}
}
} Program
async/await的实现方式:
using System;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
async static void AsyncFunction()
{
await Task.Delay();
Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作.");
for (int i = ; i < ; i++)
{
Console.WriteLine(string.Format("AsyncFunction:i={0}", i));
}
} public static void Main()
{
Console.WriteLine("主线程执行业务处理.");
AsyncFunction();
Console.WriteLine("主线程执行其他处理");
for (int i = ; i < ; i++)
{
Console.WriteLine(string.Format("Main:i={0}", i));
}
Console.ReadLine();
}
}
} Program
带返回值的方式
方式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());
return ;
} static int Getsum()
{
int sum = ;
Console.WriteLine("使用Task执行异步操作.");
for (int i = ; i < ; i++)
{
sum += i;
}
return sum;
}
}
} Program
async/await的实现:
using System;
using System.Threading.Tasks; namespace ConsoleApp1
{
class Program
{
public static void Main()
{
var ret1 = AsyncGetsum();
Console.WriteLine("主线程执行其他处理");
for (int i = ; i <= ; i++)
Console.WriteLine("Call Main()");
int result = ret1.Result; //阻塞主线程
Console.WriteLine("任务执行结果:{0}", result);
} async static Task<int> AsyncGetsum()
{
await Task.Delay();
int sum = ;
Console.WriteLine("使用Task执行异步操作.");
for (int i = ; i < ; i++)
{
sum += i;
}
return sum;
}
}
} Program
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 = ;
Console.WriteLine("使用Task执行异步操作.");
for (int i = ; i < ; 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();
}
}
} Program
任务的串行:
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();
stack.Push();
}); //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();
}
}
} Program
子任务:
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[];
//创建并启动子任务
new Task(() => { result[] = "我是子任务1。"; }, TaskCreationOptions.AttachedToParent).Start();
new Task(() => { result[] = "我是子任务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(); }
}
} Program
动态并行(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);
}
}
} Program
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 = ; i < seconds; i++)
{
Thread.Sleep(TimeSpan.FromSeconds());
if (token.IsCancellationRequested) return -;
}
return * seconds;
} private static void Main(string[] args)
{
var cts = new CancellationTokenSource();
var longTask = new Task<int>(() => TaskMethod("Task 1", , 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", , cts.Token), cts.Token);
longTask.Start();
for (int i = ; i < ; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine(longTask.Status);
}
cts.Cancel();
for (int i = ; i < ; i++)
{
Thread.Sleep(TimeSpan.FromSeconds(0.5));
Console.WriteLine(longTask.Status);
} Console.WriteLine("A task has been completed with result {0}.", longTask.Result);
}
}
} Program
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 * seconds;
} static void Main(string[] args)
{
try
{
Task<int> task = Task.Run(() => TaskMethod("Task 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();
}
}
} Program
多个任务:
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 * seconds;
} public static void Main(string[] args)
{
try
{
var t1 = new Task<int>(() => TaskMethod("Task 3", ));
var t2 = new Task<int>(() => TaskMethod("Task 4", ));
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;
});
}
}
}
} Program
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 = ; i <= ; i++)
{
Console.WriteLine("i={0}", i);
Thread.Sleep();
}
});
} 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();
}
}
} Program
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>()
{
{"","A"},
{"","B"},
{"","C"},
{"","D"},
{"","E"},
{"","F"},
}; public static void Main()
{
Task<string> task = GetValueFromCache("");
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();
Console.WriteLine("GetValueFromCache继续执行。。。。");
if (cache.TryGetValue(key, out result))
{
return Task.FromResult(result);
}
return Task.FromResult("");
} }
} Program
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 = ; i <= ; ++i)
{
Thread.Sleep();
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();
}
}
} Program
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());
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); }
}
} Program
不带回调方式的
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());
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); }
}
} Program
Task总结的更多相关文章
- Concepts:Request 和 Task
当SQL Server Engine 接收到Session发出的Request时,SQL Server OS将Request和Task绑定,并为Task分配一个Workder.在TSQL Query执 ...
- .Net多线程编程—任务Task
1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 object AsyncState 表示在 ...
- nginx+iis+redis+Task.MainForm构建分布式架构 之 (redis存储分布式共享的session及共享session运作流程)
本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,上一篇分享文章制作是在windows上使用的nginx,一般正式发布的时候是在linux来配 ...
- windows+nginx+iis+redis+Task.MainForm构建分布式架构 之 (nginx+iis构建服务集群)
本次要分享的是利用windows+nginx+iis+redis+Task.MainForm组建分布式架构,由标题就能看出此内容不是一篇分享文章能说完的,所以我打算分几篇分享文章来讲解,一步一步实现分 ...
- Openstack Periodic Task
Openstack Periodic Task 周期性任务在各个模块的manager.py(computer,scheduler,cell,network)中添加. 添加方法:在模块manager类实 ...
- MapReduce剖析笔记之三:Job的Map/Reduce Task初始化
上一节分析了Job由JobClient提交到JobTracker的流程,利用RPC机制,JobTracker接收到Job ID和Job所在HDFS的目录,够早了JobInProgress对象,丢入队列 ...
- [Java定时器]用Spring Task实现一个简单的定时器.
今天做一个项目的的时候需要用到定时器功能.具体需求是: 每个月一号触发一次某个类中的方法去拉取别人的接口获取上一个月份车险过期的用户.如若转载请附上原文链接:http://www.cnblogs.co ...
- 定时管理器框架-Task.MainForm
入住博客园4年多了,一直都是看别人的博客,学习别人的知识,为各个默默无私贡献自己技术总结的朋友们顶一个:这几天突然觉得是时候加入该队列中,贡献出自己微弱的力量,努力做到每个月有不同学习总结,知识学习的 ...
- Task三个列子的分享
这次要分享的是C#Task任务的几个列子,感觉最实用的是封装的分页任务执行方法,这个方法步奏也是目前在我工作中执行多任务常用的,不知道各位也有这用的情况,那么开始吧. 1.顺序任务执行 //顺序任务执 ...
- webapi+Task并行请求不同接口实例
标题的名称定义不知道是否准确,不过我想表达的意思就是使用Task特性来同时请求多个不同的接口,然后合并数据:我想这种场景的开发对于对接过其他公司接口的人不会陌生,本人也是列属于之内,更多的是使用最原始 ...
随机推荐
- tf.expand_dims
想要增加一维,可以使用tf.expand_dims(input, dim, name=None)函数 t = np.array(np.arange(1, 1 + 30).reshape([2, 3, ...
- .OnCommand mfc
.OnCommand是响应WM_COMMAND消息的,一般是响应控件和菜单的命令消息时使用. 如果 WM_COMMAND 来自控件的话 lParam 就是发送这个 WM_COMMAND 消息的控件的句 ...
- loj6038「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT
题目传送门 https://loj.ac/problem/6038 题解 根据树的直径的两个性质: 距离树上一个点最远的点一定是任意一条直径的一个端点. 两个联通块的并的直径是各自的联通块的两条直径的 ...
- Mysqldump导入数据库很慢的解决办法
https://blog.csdn.net/xizaihui/article/details/53103049 1.MySQLdump导出的SQL语句在导入到其他数据库的时候会相当慢,甚至几十秒才处理 ...
- exec()和元类
目录 一.exec()的作用 二.元类 2.1什么是元类,元类的作用是什么? 2.2自定义创建元类 一.exec()的作用 exec执行储存在字符串或文件中的 Python 语句,相比于 eval,e ...
- javascript实现表单提交加密
javascript实现表单提交加密 通常表单的提交有两种方式,一是直接通过html的form提交,代码如下: <form action="" method="&q ...
- 银联高校极客挑战赛 初赛 第一场 B
自学图论的码队弟弟 试图写非递归求解,然后TLE了一下午==,全程找不到bug,换成递归,一发AC 判断环写得很丑== #include<bits/stdc++.h> using name ...
- 前端通过axios和FormData实现文件上传功能遇到的坑
使用element-ui中的upload上传组件,前端上传数据参数已经传过去了,但是后端 (java) 接不到数据 (null) [解决方案] html部分: <el-button type=& ...
- [CSP-S模拟测试]:巨神兵(状压DP)
题目描述 欧贝利斯克的巨神兵很喜欢有向图,有一天他找到了一张$n$个点$m$条边的有向图.欧贝利斯克认为一个没有环的有向图是优美的,请问这张图有多少个子图(即选定一个边集)是优美的?答案对$1,000 ...
- 表单input中disabled提交后得不到值的解决办法
input的字段当为diabled时时无法获取数值得,所以最近不要用这个,我们可以用readonly带替代,即可解决这类问题.