110,533
社区成员
发帖
与我相关
我的任务
分享
Dim pd As Boolean = False
Sub Main()
Dim L As New List(Of Task)
Console.WriteLine("Start " & TimeOfDay)
Dim t = Task.Factory.StartNew(Sub()
Task.Factory.StartNew(Sub()
Do
Thread.Sleep(1000)
Loop
End Sub, Tasks.TaskCreationOptions.AttachedToParent)
Do
Thread.Sleep(100)
Loop Until pd
End Sub)
L.Add(t)
Thread.Sleep(2000) : pd = True
Task.WaitAll(L.ToArray)
Console.WriteLine("End " & TimeOfDay)
Console.Read()
End Sub
感觉不是啊,如果我不加Tasks.TaskCreationOptions.AttachedToParent的话,2秒后直接就提示End表示线程t结束了,但是他的子线程其实还在死循环中呢。
如果想不加也判断子子线程都结束的话,可以这样
Dim pd As Boolean = False
Sub Main()
Dim L As New List(Of Task)
Dim tt As Task
Console.WriteLine("Start " & TimeOfDay)
Dim t = Task.Factory.StartNew(Sub()
tt = Task.Factory.StartNew(Sub()
Do
Thread.Sleep(1000)
Loop
End Sub)
L.Add(tt)
Do
Thread.Sleep(100)
Loop Until pd
End Sub)
L.Add(t)
Thread.Sleep(2000) : pd = True
Task.WaitAll(L.ToArray)
Console.WriteLine("End " & TimeOfDay)
Console.Read()
End Sub
public static void 快速排序<T>(T[] datas) where T : IComparable<T>
{
var t0 = new Stopwatch();
t0.Start();
快速排序Async(datas, 0, datas.Length - 1).Wait();
Task.Run(()=> 记录日志(datas, t0));
}
不扩散 Task 编程。
我想说的是,其实 Task 编程思想是一种自顶向下的设计思想,所以它才比较自由。如果你过多地”自底向上拼凑“可能就会纠结这类技术问题比较多。public static async void 快速排序<T>(T[] datas) where T : IComparable<T>
{
var t0 = new Stopwatch();
t0.Start();
await 快速排序Async(datas, 0, datas.Length - 1);
await 记录日志(datas, t0);
}
这就是传染性的表现。
为什么传统的 PLinq 在 Task 面前显得有点 low 呢?就是因为 PLinq 目前还是阻塞式的,所以递归分解算法时会造成大量被阻塞和滥用的线程;而 Task 程序设计是异步的、不阻塞的,这就是其高级的地方。public static void 快速排序<T>(T[] datas) where T : IComparable<T>
{
快速排序Async(datas, 0, datas.Length - 1).Wait();
}
public static void 快速排序Sync<T>(T[] datas, int left, int right, bool 是否需要写日志 = false) where T : IComparable<T>
{
var t0 = new Stopwatch();
t0.Start();
var index = 划分(datas);
if (index - left <= right - index)
{
快速排序Sync(datas, left, index - 1);
快速排序Sync(datas, index + 1, right);
写日志(datas, left, right, index, t0);
}
else
{
快速排序Sync(datas, index + 1, right);
快速排序Sync(datas, left, index - 1);
写日志(datas, left, right, index, t0);
}
}
public static Task 快速排序Async<T>(T[] datas, int left, int right, bool 是否需要写日志 = false) where T : IComparable<T>
{
if (right - left < 10000)
{
快速排序Sync(datas, left, right, 是否需要写日志);
return Task.CompletedTask;
}
else
{
var t0 = new Stopwatch();
t0.Start();
var index = 划分(datas);
if (index - left <= right - index)
{
var t1 = 快速排序Async(datas, left, index - 1);
var t2 = 快速排序Async(datas, index + 1, right);
return Task.Run(() =>
{
Task.WaitAll(t1, t2);
写日志(datas, left, right, index, t0, t1, t2);
});
}
else
{
var t2 = 快速排序Async(datas, left, index - 1);
var t1 = 快速排序Async(datas, index + 1, right);
return Task.Run(() =>
{
Task.WaitAll(t1, t2);
写日志(datas, left, right, index, t0, t1, t2);
});
}
}
首先要区分到底是否要记录日志,因为你的目的是要记录日志,这里设计了用来告知递归函数是否要记录日志的参数,你可以修改参数设计来实现你的控制方式。
函数中要判断是否值得使用并发异步算法,这里假设当规模大于1万时才使用并发异步操作,否则还是使用同步单线程算法。