Async In C#5.0(async/await)学习笔记

此文为Async in C#5.0学习笔记

1、在async/await之前的异步

方式一:基于事件的异步Event-based Asynchronous Pattern (EAP).

private void DumpWebPage(Uri uri)
{
    WebClient webClient = new WebClient();
    webClient.DownloadStringCompleted += OnDownloadStringCompleted;
    webClient.DownloadStringAsync(uri);
}
private void OnDownloadStringCompleted(object sender, DownloadStringCompletedEventArgs eventArgs)
{
    m_TextBlock.Text = eventArgs.Result;
}

方式二:基于IAsyncResult接口的异步

private void LookupHostName()
{
    object unrelatedObject = "hello";
    Dns.BeginGetHostAddresses("oreilly.com", OnHostNameResolved, unrelatedObject);
}
private void OnHostNameResolved(IAsyncResult ar)
{
    object unrelatedObject = ar.AsyncState;//上文中的hello字符串
    IPAddress[] addresses = Dns.EndGetHostAddresses(ar);
    // Do something with addresses
}

方式三:回调

void GetHostAddress(string hostName, Action<IPAddress> callback)
{
    //..
}

private void LookupHostName2()
{
    GetHostAddress("oreilly.com", OnHostNameResolved);
}
private void OnHostNameResolved(IPAddress address)
{
    // Do something with address
}

private void LookupHostName3()
{
    GetHostAddress("oreilly.com", address =>
    {
        // Do something with address and aUsefulVariable
    });
}

方式四:使用Task,尤其是Task<T>

private void LookupHostNameByTask()
{
    Task<IPAddress[]> ipAddressesPromise = Dns.GetHostAddressesAsync("oreilly.com");
    ipAddressesPromise.ContinueWith(_ =>
    {
        IPAddress[] ipAddresses = ipAddressesPromise.Result;
        // Do something with address
        Console.WriteLine("In ContinueWith");//后输出
    });
    Console.WriteLine("After ContinueWith");//先输出
}

共同的缺陷:必须将方法分为两部分
乱如麻的递归

private void LookupHostNames(string[] hostNames)
{
    LookUpHostNamesHelper(hostNames, 0);
}
private static void LookUpHostNamesHelper(string[] hostNames, int i)
{
    Task<IPAddress[]> ipAddressesPromise = Dns.GetHostAddressesAsync(hostNames[i]);
    ipAddressesPromise.ContinueWith(_ =>
    {
        IPAddress[] ipAddresses = ipAddressesPromise.Result;
        // Do something with address
        if (i + 1 < hostNames.Length)
        {
            LookUpHostNamesHelper(hostNames, i + 1);
        }
    });
}

2、使用Async

private async void DumpWebPageAsync(string uri)
{
    WebClient webClient = new WebClient();
    string page = await webClient.DownloadStringTaskAsync(uri);
    Console.WriteLine(page);
}

async/await

Task<string> myTask = webClient.DownloadStringTaskAsync(uri);
// Do something here
string page = await myTask;

注意,下面这样操作可能会有隐患,当firstTask有异常时,将不执行await secondTask

Task<string> firstTask = webClient1.DownloadStringTaskAsync("http://oreilly.com");
Task<string> secondTask = webClient2.DownloadStringTaskAsync("http://simple-talk.com");
string firstPage = await firstTask;
string secondPage = await secondTask;

3、Async方法的返回类型

1、void
2、Task
3、Task<T>

4、Async方法具有传递性

private async Task<int> GetPageSizeAsync(string url)
{
    WebClient webClient = new WebClient();
    string page = await webClient.DownloadStringTaskAsync(url);
    return page.Length;
}

private async Task<string> FindLargestWebPage(string[] urls)
{
    string largest = null;
    int largestSize = 0;
    foreach (string url in urls)
    {
        int size = await GetPageSizeAsync(url);
        if (size > largestSize)
        {
            size = largestSize;
            largest = url;
        }
    }
    return largest;
}

5、Async匿名委托和Lambdas表达式

Func<Task<int>> getNumberAsync = async delegate { return 3; };
Func<Task<string>> getWordAsync = async () => "hello";

6、await实际上做了啥?

同时执行下面两个分支
1、从当前行返回跳出函数,执行其他代码
2、等待await异步执行完成后,继续执行当行后面的语句
注意不恰当的大量使用异步,会必正常使用同步慢。

6、哪里不能使用await

1、catch和finally块

/// <summary>
/// 错误的写法
/// </summary>
private async void InvalidMethodAsync()
{
    var webClient = new WebClient();
    string page;
    try
    {
        page = await webClient.DownloadStringTaskAsync("http://oreilly.com");
    }
    catch (WebException)
    {
        page = await webClient.DownloadStringTaskAsync("http://oreillymirror.com");
    }
}
/// <summary>
/// 正确的写法
/// </summary>
private async void InsteadMethodAsync()
{
    bool failed = false;
    var webClient = new WebClient();
    string page;
    try
    {
        page = await webClient.DownloadStringTaskAsync("http://oreilly.com");
    }
    catch (WebException)
    {
        failed = true;
    }
    if (failed)
    {
        page = await webClient.DownloadStringTaskAsync("http://oreillymirror.com");
    }
}

2、lock块

不在lock内使用await

private async void LockAsync()
{
    var sync = new object();
    lock (sync)
    {
        // Prepare for async operation
    }
    int myNum = await Task.Run(() => { Thread.Sleep(5000); return 1; });
    lock (sync)
    {
        // Use result of async operation
    }
}

3、LINQ查询表达式

private async void LINQQueryAsync()
{
    var alexsInts = new List<int>();
    IEnumerable<Task<int>> tasks = alexsInts
                                   .Where(x => x != 9)
                                   .Select(async x => await DoSomthingAsync(x) + await DoSomthingElseAsync(x));
    IEnumerable<int> transformed = await Task.WhenAll(tasks);
}

private async Task<int> DoSomthingAsync(int x)
{
    return await Task.Run(() => { return x * 2; });
}

private async Task<int> DoSomthingElseAsync(int x)
{
    return await Task.Run(() => { return x + 2; });
}

4、Unsafe Code

不能在unsafe代码块中使用await

7、异常捕获

异步内的异常不会直接抛出,可通过Task的IsFaulted判断

private async void ExceptionCaptureAsync()
{
    var task = ThrownExceptionAsync();
    Console.WriteLine($"1 task.IsFaulted={task.IsFaulted}");
    try
    {
        var result=await task;
        Console.WriteLine("Finished");
    }
    catch(Exception ex)
    {
        Console.WriteLine($"2 Exception:{ex.Message}");
    }
    Console.WriteLine("3 Exit ExceptionCaptureAsync");
}

private async Task<int> ThrownExceptionAsync()
{
    throw new Exception("In ThrownExceptionAsync");
}

输出结果:
在这里插入图片描述

8、async方法在需要之前是同步的

一般来说,async方法,在遇到第一个await之前是同步的。
其他情况:

  • 获取task的result
  • 未到达await时已经return
  • 运行了异步代码(但已执行完成)
  • 到达await时,异步方法也已执行完成

9、基于任务的异步模式(Task-Based Asynchronous Pattern,TAP)

同步方法

  • 有或没有参数,尽量避免ref与out参数
  • 有返回类型
  • 正确的方法名
  • 常见或预期的异常是返回类型的一部分,意外异步应该把抛出
    如:
public static IPHostEntry GetHostEntry(string hostNameOrAddress)

异步方法

  • 有或没有参数,不能有ref或out参数
  • 返回类型为Task或Task<T>
  • 命名格式为NameAsync(以Async结尾)
  • 错误的使用应直接抛出,其他异常在Task内处理
public static async Task<IPHostEntry> GetHostEntryAsync(string hostNameOrAddress)

10、使用Task进行计算密集型操作

Task t = Task.Run(() => MyLongComputation(a, b));

await Task.Run(() => MyLongComputation(a, b));
private async Task<int> TaskDemoAsync()
{
    int a = 0, b = 0;
    CancellationToken cancellationToken = new CancellationToken();
    CustomTaskScheduler taskScheduler = new CustomTaskScheduler();

    var t1 = Task.Factory.StartNew(() => { return MyLongComputation(a, b); },
                                    cancellationToken,
                                    TaskCreationOptions.LongRunning,
                                    taskScheduler);
    return await t1;
}

private static int MyLongComputation(int a,int b)
{
    return a + b;
}
//https://www.infoworld.com/article/3063560/how-to-build-your-own-task-scheduler-in-csharp.html
public sealed class CustomTaskScheduler : TaskScheduler, IDisposable
{
    private BlockingCollection<Task> tasksCollection = new BlockingCollection<Task>();
    private readonly Thread mainThread = null;
    public CustomTaskScheduler()
    {
        mainThread = new Thread(new ThreadStart(Execute));
        if (!mainThread.IsAlive)
        {
            mainThread.Start();
        }
    }
    private void Execute()
    {
        foreach (var task in tasksCollection.GetConsumingEnumerable())
        {
            TryExecuteTask(task);
        }
    }
    protected override IEnumerable<Task> GetScheduledTasks()
    {
        return tasksCollection.ToArray();
    }
    protected override void QueueTask(Task task)
    {
        if (task != null)
            tasksCollection.Add(task);
    }
    protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
    {
        return false;
    }
    private void Dispose(bool disposing)
    {
        if (!disposing) return;
        tasksCollection.CompleteAdding();
        tasksCollection.Dispose();
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

11、创建Puppet Task

//没有PermissionDialog类
//没有async关键词
private Task<bool> GetUserPermission()
{
    // Make a TaskCompletionSource so we can return a puppet Task
    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
    // Create the dialog ready
    PermissionDialog dialog = new PermissionDialog();
    // When the user is finished with the dialog, complete the Task using SetResult
    dialog.Closed += delegate { tcs.SetResult(dialog.PermissionGranted); };
    // Show the dialog
    dialog.Show();
    // Return the puppet Task, which isn't completed yet
    return tcs.Task;
}

private async void GetUserPermissionAsync()
{
    if(await GetUserPermission())
    {
        //Do something
    }
}

12、旧的异步交互

IAsyncResult BeginGetHostEntry(string hostNameOrAddress,
				AsyncCallback requestCallback,
				object stateObject)
IPHostEntry EndGetHostEntry(IAsyncResult asyncResult)

public static Task<IPHostEntry> GetHostEntryAsync(string hostNameOrAddress)
{
    TaskCompletionSource<IPHostEntry> tcs = new TaskCompletionSource<IPHostEntry>();
    Dns.BeginGetHostEntry(hostNameOrAddress, asyncResult =>
    {
        try
        {
            IPHostEntry result = Dns.EndGetHostEntry(asyncResult);
            tcs.SetResult(result);
        }
        catch (Exception e)
        {
            tcs.SetException(e);
        }
    }, null);
    return tcs.Task;
}

private async void FromAsyncDemo()
{
    string hostNameOrAddress = "www.baidu.com";
    var t = Task<IPHostEntry>.Factory.FromAsync<string>(Dns.BeginGetHostEntry,
            Dns.EndGetHostEntry,
            hostNameOrAddress,
            null);
    await t;
    Console.WriteLine($"Dns:{t.Result.AddressList.FirstOrDefault()}");
}

13、延时(Task.Delay)

一般延时

await Task.Run(() => Thread.Sleep(100));

使用Timer和TaskCompletionSource(直接使用Task.Delay即可)

private static Task Delay(int millis)
{
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
    System.Threading.Timer timer = new System.Threading.Timer(_ => tcs.SetResult(null), null, millis, Timeout.Infinite);
    tcs.Task.ContinueWith(delegate { timer.Dispose(); });
    return tcs.Task;
}

14、等待所有Task完成(Task.WhenAll)

private async void TaskWhenAllDemoAsync()
{
    List<Task<string>> tasks = new List<Task<string>>();
    List<string> domains = new List<string>() { "1", "2", "3" };
    var rnd = new Random((int)DateTime.Now.Ticks);
    foreach (string domain in domains)
    {
        tasks.Add(GetStringAsync(domain, rnd.Next(100, 1000)));
    }
    //等价
    //var tasks2 = domains.Select(domain => GetStringAsync(domain, rnd.Next(100, 1000)));

    var allTask = Task.WhenAll(tasks);
    var taskResult = await allTask;
    
    foreach (var str in taskResult)
    {
        Console.WriteLine($"domain:{str}");
    }
}

private async Task<string> GetStringAsync(string domain, int sleepTime)
{
    var task = Task.Run(() =>
    {
        Task.Delay(sleepTime);
        Console.WriteLine($"Delay:{sleepTime}ms in Domain:{domain}");
        return domain;
    });
    return await task;
}

输出结果:
在这里插入图片描述

15、等待Task列表中的任一个完成(Task.WhenAny)

public static Task WhenAny(IEnumerable tasks)

private async void WhenAnyDemoAsync()
{
    var domains = new List<string>() { "1", "2", "3" };
    var rnd = new Random((int)DateTime.Now.Ticks);            
    var tasks = domains.Select(domain => GetStringAsync(domain, rnd.Next(100, 1000))).ToList();
    //注意上面与下面运行的结果差别
    // The IEnumerable from Select is lazy, so evaluate it to start the tasks
    //var tasks = domains.Select(domain => GetStringAsync(domain, rnd.Next(100, 1000)));
    Task<Task<string>> anyTask=Task.WhenAny(tasks);//注意,如果没有ToList(),当前才执行tasks内的GetStringAsync函数
    Task<string> winner=await anyTask;
    string strDomain=await winner;
    Console.WriteLine($"Domain:{strDomain}");
    await Task.WhenAll(tasks);//注意,如果没有ToList,这里的task与上面的是两次结果
    Console.WriteLine($"============================\r\n");
}

16、自定义组合

超时时退出

private async Task<T> WithTimeout<T>(Task<T> task, int time)
{
    Task delayTask = Task.Delay(time);
    Task firstToFinish = await Task.WhenAny(task, delayTask);
    if (firstToFinish == delayTask)
    {
        // The delay finished first - deal with any exception
        _ = task.ContinueWith(HandleException);
        throw new TimeoutException();
    }
    return await task; // If we reach here, the original task already finished
}

private static void HandleException<T>(Task<T> task)
{
    if (task.Exception != null)
    {
        //Log Exception
        //Logging.LogException(task.Exception);
    }
}

17、取消异步操作

CancellationTokenSource cts = new CancellationTokenSource();
cancelButton.Click += delegate { cts.Cancel(); };
int result = await dbCommand.ExecuteNonQueryAsync(cts.Token);

foreach (var x in thingsToProcess)
{
cancellationToken.ThrowIfCancellationRequested();//then IsCanceled will be true
// Process x ...
}

18、异步操作期间返回进度

使用 IPRogress<T>

Task<byte[]> DownloadDataTaskAsync(Uri address,
CancellationToken cancellationToken,
IProgress<DownloadProgressChangedEventArgs> progress)

new Progress<int>(percentage => progressBar.Value = percentage);

private Task<byte[]> DownloadDataTaskAsync(Uri address,
                CancellationToken cancellationToken,
                IProgress<int> progress)
{
    var currPercent = 1;
    progress.Report(currPercent);
    return null;
}

private void ReturnProgress()
{
    var progress= new Progress<int>(percentage => progressBar1.Value = percentage);
    progress.ProgressChanged += Progress_ProgressChanged;
}

19、异步操作的生命周期

private async void btn_GetIcon_Click(object sender, EventArgs e)
{
    Console.Clear();
    Enqueue($"1\tStart in btn_GetIcon_Click");
    var task = GetFavIcon("www.csdn.net");
    Enqueue($"3\tStart await GetFavIcon");
    var ico = await task;
    Enqueue($"6\tFinish await in btn_GetIcon_Click,{ico}");
    while(queue.TryDequeue(out string result))
    {
        Console.WriteLine(result);
    }
    
}

private async Task<string> GetFavIcon(string url)
{
    Enqueue($"2\tIn GetFavIcon function");
    var task = Task.Run(() =>
    {
        Enqueue($"3\tStart to GetfavIcon for {url}");
        var spendTime = rndNum.Next(1000, 1500);
        Task.Delay(spendTime);
        Enqueue($"4\tSpend {spendTime}ms To Getfavicon for {url}");
        return url;
    });
    Enqueue($"3\tStart await in GetFavicon");
    var result = await task;
    Enqueue($"5\tFinish await in GetFavicon");
    return $"favicon:{result}";
}

private void Enqueue(string msg)
{
    queue.Enqueue($"{DateTime.Now:HH:mm:ss.FFFFFFF}\t{msg}");
}

输出结果:
在这里插入图片描述
序号为3的输出顺序可能不一致。

20、选择不使用SynchronizationContext(ConfigureAwait)

没太明白

21、异步方法的Result属性

var result = AlexsMethodAsync().Result;

程序会阻塞等待AlexsMethodAsync执行结束

22、异步的异常

async Task CatcherAsync()
{
    try
    {
        Console.Clear();
        Console.WriteLine("In CatcherAsync");
        var task = Thrower();
        Console.WriteLine("Before await Thrower");
        await task;
        Console.WriteLine("After await Thrower");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Cathc Exception in Catcher:{ex.Message}");
    }
}
async Task Thrower()
{
    await Task.Delay(100);
    throw new Exception("Exception in Thrower");
}

private async void btn_ExceptionDemo_Click(object sender, EventArgs e)
{
    await CatcherAsync();
}

输出结果:
在这里插入图片描述

23、使用.ContinueWith(HandleException)处理void类型异步

public static void ForgetSafely(this Task task)
{
    task.ContinueWith(HandleException);
}

private static void HandleException(Task task)
{
    //do something task.Exception
}

24、AggregateException和WhenAll

Task<Image[]> allTask = Task.WhenAll(tasks);
try
{
    await allTask;
}
catch
{
    foreach (Exception ex in allTask.Exception.InnerExceptions)
    {
        // Do something with exception
    }
}

25、尽量在同步模块时抛出异常

private Task<Image> GetFaviconAsync(string domain)
{
    if (domain == null) throw new ArgumentNullException("domain");
    return GetFaviconAsyncInternal(domain);
}
private async Task<Image> GetFaviconAsyncInternal(string domain)
{
    //...
}

26、异步里,finally不一定执行

await DelayForever()及finally里的代码没有执行

async void AlexsMethod()
{
    try
    {
        Console.WriteLine("Before DelayForever");
        await DelayForever();
        Console.WriteLine("After DelayForever");
    }
    finally
    {
        // Never happens
        Console.WriteLine("finally,After DelayForever");
    }
}
Task DelayForever()
{
    Console.WriteLine("IN DelayForever");
    return new TaskCompletionSource<object>().Task;
}

27、lock块内不能使用await

lock (sync)
{
// Prepare for async operation
}
int myNum = await AlexsMethodAsync();
lock (sync)
{
// Use result of async operation
}

if (DataInvalid())
{
	Data d = await GetNewData();
	// Anything could have happened in the await
	if (DataInvalid())
	{
		SetNewData(d);
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/302688.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VMware安装与CentOS8安装与配置

VMware安装与CentOS8安装与配置 话不多说&#xff0c;咱们开始干&#xff0c;文末附资料哦~ 一、安装VMware 1、双击安装包 2、如提出什么重启&#xff0c;重启就是了 3、按照提示下一步 4、选择安装目录&#xff0c;下一步 5、取消勾选&#xff0c;下一步 安装完成后&…

【FPGA】分享一些FPGA数字信号处理相关的书籍

在做FPGA工程师的这些年&#xff0c;买过好多书&#xff0c;也看过好多书&#xff0c;分享一下。 后续会慢慢的补充书评。 【FPGA】分享一些FPGA入门学习的书籍【FPGA】分享一些FPGA协同MATLAB开发的书籍 【FPGA】分享一些FPGA视频图像处理相关的书籍 【FPGA】分享一些FPGA高速…

【愚公系列】2023年12月 HarmonyOS教学课程 054-Web组件(基本使用和属性)

&#x1f3c6; 作者简介&#xff0c;愚公搬代码 &#x1f3c6;《头衔》&#xff1a;华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xf…

【python】使用fitz包读取PDF文件报错“ModuleNotFoundError: No module named ‘frontend‘”

【python】使用fitz包读取PDF文件报错“ModuleNotFoundError: No module named ‘frontend’” 正确解决过程 在读取PDF文件时&#xff0c;我使用了fitz包&#xff0c;当使用代码import fitz导入该包时&#xff0c;出现了报错&#xff1a; 于是我直接使用以下代码安装fronten…

Vmware安装windowsServer2022版本

虚拟机配置 文件->新建虚拟机 典型安装与自定义安装 典型安装&#xff1a;VMware会将主流的配置应用在虚拟机的操作系统上&#xff0c;对于新手来很友好。 自定义安装&#xff1a;自定义安装可以针对性的把一些资源加强&#xff0c;把不需要的资源移除。避免资源的浪费。…

二叉树的直径,力扣

目录 题目地址&#xff1a; 题目&#xff1a; 我们直接看题解吧&#xff1a; 审题目事例提示&#xff1a; 解题方法&#xff1a; 难度分析&#xff1a; 解题方法分析&#xff1a; 解题分析&#xff1a; 补充说明&#xff1a; 代码优化&#xff1a; 题目地址&#xff1a; 543. 二…

设计模式的艺术P1基础—2.2 类与类的UML图示

设计模式的艺术P1基础—2.2 类与类的UML图示 在UML 2.0的13种图形中&#xff0c;类图是使用频率最高的两种UML图之一&#xff08;另一种是用于需求建模的用例图&#xff09;&#xff0c;它用于描述系统中所包含的类以及它们之间的相互关系&#xff0c;帮助人们简化对系统的理解…

指针传参误区

C语言中指针作为形参传递时&#xff0c;func&#xff08;*a, *b&#xff09; 这种形式的话&#xff0c;是无法通过简单的 ab来修改的&#xff0c;在函数体内a的地址确实被修改成b的地址了&#xff0c;但是当函数执行结束时&#xff0c;a的地址会重新回到原本的地址里面&#xf…

Mac安装upx及不同os计算md5值

Mac安装upx 最近需要将exe文件打包到pod内部&#xff0c;为了减少包占用磁盘空间&#xff0c;需要借用upx对windows exe文件进行压缩。 1 概念&#xff1a;压缩工具 UPX 全称是 “Ultimate Packer for eXecutables”&#xff0c;是一个免费、开源、编写、可扩展、高性能的可执行…

【C语言】编程世界的不朽基石与未来展望

C语言&#xff0c;一种经久不衰的高级编程语言&#xff0c;自1972年由Dennis Ritchie在AT&T贝尔实验室开发以来&#xff0c;已深深扎根于编程语言的发展历程中。它既是计算机科学史上的一个重要里程碑&#xff0c;也是现代软件开发的核心支柱。从操作系统到嵌入式系统的构建…

设计模式的艺术P1基础—第1章 概述

刘伟&#xff0c;2020 概述&#xff1a;4部分&#xff0c;26章。 P1:基础&#xff08;1-2章&#xff09; P2:创建型设计模式&#xff08;创建艺术&#xff0c;3-8章&#xff09; P3:结构型设计模式&#xff08;组合艺术&#xff0c;9-15章&#xff09; P4:行为型设计模式&…

基于Python的车牌识别系统实现

本文将以基于Python的车牌识别系统实现为方向,介绍车牌识别技术的基本原理、常用算法和方法,并详细讲解如何利用Python语言实现一个完整的车牌识别系统。 精彩专栏持续更新推荐订阅,收藏关注不迷路 微信小程序实战开发专栏 目录 引言车牌识别技术的应用场景Python在车牌识别…

从零学Java - String类

Java String类 文章目录 Java String类1 String1.1 常用两种创建方式1.2 比较两种创建方式1.3 字符串不可变性1.4 面试题 2 常用方法2.1 练习 3 可变字符串3.1 常用方法3.2 验证StringBuilder的高效性3.3 练习3.4 面试题: 4 正则表达式4.1 元字符4.2 其他字符4.2.1 预定义字符4…

MLP(多层感知机) 虚战1

使用Keras实现MLP 前两节地址&#xff1a; CSDNmatplotlib 虚战1-CSDN博客 &#xff08;数据的获取在这有说明&#xff09; 数据预处理 虚战1-CSDN博客CSDN 数据预处理的最后一步&#xff1a;将数据集分为 训练数据集、测试数据集和校验数据集。 训练数据集&#xff1a…

C++学习笔记——友元及重载运算符

目录 一、友元 1.1声明友元函数 1.2声明友元类 二、运算符重载 2.1重载加号运算符 2.2重载流插入运算符 三、一个简单的银行管理系统 四、 详细的介绍 一、友元 在 C 中&#xff0c;友元是一个函数或类&#xff0c;它可以访问另一个类的私有成员或保护成员。通常情况下…

RT-Thread 线程管理

线程管理 在日常生活中&#xff0c;我们要完成一个大任务&#xff0c;一般会将它分解成多个简单、容易解决的小问题&#xff0c;小问题逐个被解决&#xff0c;大问题也就随之解决了。 在多线程操作系统中&#xff0c;也同样需要开发人员把一个复杂的应用分解成多个小的、可调…

k8s--集群调度(kube-scheduler)

了解kube-scheduler 由之前博客可知kube-scheduler是k8s中master的核心组件之一 scheduler&#xff1a;负责调度资源。把pod调度到node节点。他有两种策略&#xff1a; 预算策略&#xff1a;人为部署&#xff0c;指定node节点去部署新建的pod 优先策略&#xff1a;通过算法选…

FineBI实战项目一(11):每日不同商品分类订单个数统计

1 明确数据分析目标 统计所有订单中的每种分类对应的商品的个数&#xff0c;构建词云图 2 创建用于保存数据分析结果的表 create table app_cat_cnt(id int primary key auto_increment,daystr varchar(20),catName varchar(100),cnt int ); 3 编写SQL语句进行数据分析 se…

亲测有效:腾讯云免费服务器30天申请流程

腾讯云免费服务器申请入口 https://curl.qcloud.com/FJhqoVDP 免费服务器可选轻量应用服务器和云服务器CVM&#xff0c;轻量配置可选2核2G3M、2核8G7M和4核8G12M&#xff0c;CVM云服务器可选2核2G3M和2核4G3M配置&#xff0c;腾讯云百科txybk.com分享2024年最新腾讯云免费服务器…

「MCU」SD NAND芯片之国产新选择优秀

文章目录 前言 传统SD卡和可贴片SD卡 传统SD卡 可贴片SD卡 实际使用 总结 前言 随着目前时代的快速发展&#xff0c;即使是使用MCU的项目上也经常有大数据存储的需求。可以看到经常有小伙伴这样提问&#xff1a; 大家好&#xff0c;请问有没有SD卡芯片&#xff0c;可以…