您现在的位置是:首页 >其他 >【C# .NET】chapter 13 使用多任务改进性能和可扩展性网站首页其他
【C# .NET】chapter 13 使用多任务改进性能和可扩展性
简介【C# .NET】chapter 13 使用多任务改进性能和可扩展性
目录
二、 对比 string的“+”操作与stringbuilder 操作 的处理效率,内存消耗情况,
三、异步运行任务、三种启动任务方法、将上一任务方法处理结果作为参数传给下一任务方法
五、同步访问共享资源 Monitor.TryEnter、Monitor.Exit、 原子操作 Interlocked.Increment
六、理解async 和 await :改进控制台响应。 Main方法async Task
一、物理内存和虚拟内存使用(Recorder 类)
using System;
using System.Diagnostics;
using static System.Console;
using static System.Diagnostics.Process;
namespace Packt.Shared
{
public static class Recorder
{
static Stopwatch timer = new Stopwatch();
static long bytesPhysicalBefore = 0;
static long bytesVirtualBefore = 0;
public static void Start()
{
// force two garbage collections to release memory that is no
// longer referenced but has not been released yet
// // 强制两次垃圾回收释放不再被引用但尚未释放的内存
GC.Collect();
GC.WaitForPendingFinalizers();//挂起当前线程,直到正在处理终结器队列的线程清空该队列。
GC.Collect();//强制立即对所有代进行垃圾回收。
//存储当前物理和虚拟内存使用 store the current physical and virtual memory use
bytesPhysicalBefore = GetCurrentProcess().WorkingSet64;
bytesVirtualBefore = GetCurrentProcess().VirtualMemorySize64;
timer.Restart();
}
public static void Stop()
{
timer.Stop();
long bytesPhysicalAfter = GetCurrentProcess().WorkingSet64;//计时停止时的 物理内存和虚拟内存使用
long bytesVirtualAfter = GetCurrentProcess().VirtualMemorySize64;
WriteLine("{0:N0} physical bytes used.",
bytesPhysicalAfter - bytesPhysicalBefore);
WriteLine("{0:N0} virtual bytes used.",
bytesVirtualAfter - bytesVirtualBefore);
WriteLine("{0} time span ellapsed.", timer.Elapsed);
WriteLine("{0:N0} total milliseconds ellapsed.",
timer.ElapsedMilliseconds);//获取当前实例测量的总运行时间,以毫秒为单位。
}
}
}
二、 对比 string的“+”操作与stringbuilder 操作 的处理效率,内存消耗情况,
using System;
using System.Linq;
using Packt.Shared;
using static System.Console;
namespace MonitoringApp
{
class Program
{
static void Main(string[] args)
{
/*
WriteLine("Processing. Please wait...");
Recorder.Start();
// simulate a process that requires some memory resources...
int[] largeArrayOfInts = Enumerable.Range(1, 10_000).ToArray();
// ...and takes some time to complete
System.Threading.Thread.Sleep(new Random().Next(5, 10) * 1000);
Recorder.Stop();
*/
int[] numbers = Enumerable.Range(1, 50_000).ToArray();//生成指定范围内的整数序列。
WriteLine("Using string with +");
Recorder.Start();
string s = "";
for (int i = 0; i < numbers.Length; i++)
{
s += numbers[i] + ", ";
}
Recorder.Stop();
/*
Using string with +
35,196,928 physical bytes used.
6,291,456 virtual bytes used.
00:00:04.0648349 time span ellapsed.
4,064 total milliseconds ellapsed.
Using StringBuilder
0 physical bytes used.
0 virtual bytes used.
00:00:00.0018665 time span ellapsed.
1 total milliseconds ellapsed.
*/
WriteLine("Using StringBuilder");
Recorder.Start();
var builder = new System.Text.StringBuilder();
for (int i = 0; i < numbers.Length; i++)
{
builder.Append(numbers[i]); builder.Append(", ");
}
Recorder.Stop();
ReadLine();
}
}
}
三、异步运行任务、三种启动任务方法、将上一任务方法处理结果作为参数传给下一任务方法
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using static System.Console;
namespace WorkingWithTasks
{
class Program
{
static void MethodA()
{
WriteLine("Starting Method A...");
Thread.Sleep(3000); // simulate three seconds of work
WriteLine("Finished Method A.");
}
static void MethodB()
{
WriteLine("Starting Method B...");
Thread.Sleep(2000); // simulate two seconds of work
WriteLine("Finished Method B.");
}
static void MethodC()
{
WriteLine("Starting Method C...");
Thread.Sleep(1000); // simulate one second of work
WriteLine("Finished Method C.");
}
static decimal CallWebService()
{
WriteLine("Starting call to web service...");
Thread.Sleep((new Random()).Next(2000, 4000));
WriteLine("Finished call to web service.");
return 89.99M;
}
static string CallStoredProcedure(decimal amount)
{
WriteLine("Starting call to stored procedure...");
Thread.Sleep((new Random()).Next(2000, 4000));
WriteLine("Finished call to stored procedure.");
return $"12 products cost more than {amount:C}.";
}
static void Main(string[] args)
{
var timer = Stopwatch.StartNew();
// WriteLine("Running methods synchronously on one thread.");
// MethodA();
// MethodB();
// MethodC();
/* //开启任务的三种方法
WriteLine("Running methods asynchronously on multiple threads.");
Task taskA = new Task(MethodA);
taskA.Start();
Task taskB = Task.Factory.StartNew(MethodB);
Task taskC = Task.Run(new Action(MethodC));
Task[] tasks = { taskA, taskB, taskC };
Task.WaitAll(tasks);
*/
WriteLine("Passing the result of one task as an input into another.");
//将CallWebService的结果作为输入传给CallStoredProcedure任务
var taskCallWebServiceAndThenStoredProcedure =
Task.Factory.StartNew(CallWebService)
.ContinueWith(previousTask =>
CallStoredProcedure(previousTask.Result));
WriteLine($"Result: {taskCallWebServiceAndThenStoredProcedure.Result}");
WriteLine($"{timer.ElapsedMilliseconds:#,##0}ms elapsed.");
ReadLine();
}
}
}
四、嵌套子任务
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using static System.Console;
namespace NestedAndChildTasks
{
class Program
{
static void OuterMethod()
{
WriteLine("Outer method starting...");
var inner = Task.Factory.StartNew(InnerMethod,
TaskCreationOptions.AttachedToParent);//开启嵌套任务
WriteLine("Outer method finished.");
}
static void InnerMethod()//嵌套子任务方法
{
WriteLine("Inner method starting...");
Thread.Sleep(2000);
WriteLine("Inner method finished.");
}
static void Main(string[] args)
{
var outer = Task.Factory.StartNew(OuterMethod);
outer.Wait();//等待嵌套子任务完成后才继续
WriteLine("Console app is stopping.");
}
}
}
五、同步访问共享资源 Monitor.TryEnter、Monitor.Exit、 原子操作 Interlocked.Increment
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using static System.Console;
namespace SynchronizingResourceAccess
{
class Program
{
static Random r = new Random();
static string Message; // 一个共享资源
static int Counter; //另一共享资源
static object conch = new object();//互斥锁
static void MethodA()
{
try
{ //在指定的时间内尝试获取指定对象的独占锁。
if (Monitor.TryEnter(conch, TimeSpan.FromSeconds(15)))
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(r.Next(2000));
Message += "A";
Interlocked.Increment(ref Counter);//递增指定变量并将结果存储为原子操作。
Write(".");
}
}
else
{
WriteLine("Method A failed to enter a monitor lock.");
}
}
finally
{
Monitor.Exit(conch);//释放指定对象上的独占锁。
}
}
static void MethodB()
{
try
{
if (Monitor.TryEnter(conch, TimeSpan.FromSeconds(15)))
{
for (int i = 0; i < 5; i++)
{
Thread.Sleep(r.Next(2000));
Message += "B";
Interlocked.Increment(ref Counter);
Write(".");
}
}
else
{
WriteLine("Method B failed to enter a monitor lock.");
}
}
finally
{
Monitor.Exit(conch);
}
}
/*
Please wait for the tasks to complete.
..........
Results: AAAAABBBBB.
9,083 elapsed milliseconds.
10 string modifications.
*/
static void Main(string[] args)
{
WriteLine("Please wait for the tasks to complete.");
Stopwatch watch = Stopwatch.StartNew();
Task a = Task.Factory.StartNew(MethodA);
Task b = Task.Factory.StartNew(MethodB);
Task.WaitAll(new Task[] { a, b });
WriteLine();
WriteLine($"Results: {Message}.");
WriteLine($"{watch.ElapsedMilliseconds:#,##0} elapsed milliseconds.");
WriteLine($"{Counter} string modifications.");
ReadLine();
}
}
}
六、理解async 和 await :改进控制台响应。 Main方法async Task
从C#6开始可以在trycatch块中使用await
using System;
using System.Net.Http;
using System.Threading.Tasks;
using static System.Console;
namespace AsyncConsole
{
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
HttpResponseMessage response =
await client.GetAsync("http://www.apple.com/");
WriteLine("Apple's home page has {0:N0} bytes.",
response.Content.Headers.ContentLength);
}
}
}
七、支持多任务的普通类型
八、异步流 返回类型IEnumerable
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using static System.Console;
namespace AsyncEnumerable
{
class Program
{
async static IAsyncEnumerable<int> GetNumbers()
{
var r = new Random();
// simulate work
await Task.Run(() => Task.Delay(r.Next(1500, 3000)));
yield return r.Next(0, 1001);
await Task.Run(() => Task.Delay(r.Next(1500, 3000)));
yield return r.Next(0, 1001);
await Task.Run(() => Task.Delay(r.Next(1500, 3000)));
yield return r.Next(0, 1001);
}
static async Task Main(string[] args)
{
await foreach (int number in GetNumbers())
{
WriteLine($"Number: {number}");
}
}
}
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。