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

news2024/11/19 2:26:32

此文为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);
	}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【大数据进阶第三阶段之ClickHouse学习笔记】ClickHouse的简介和使用

1、ClickHouse简介 ClickHouse是一种列式数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;专门用于高性能数据分析和数据仓库应用。它是一个开源的数据库系统&#xff0c;最初由俄罗斯搜索引擎公司Yandex开发&#xff0c;用于满足大规模数据分析和报告的需求。 开源地址…

01-shell

shell 1. shell概述 1.1 引入 完成以下任务: 判断用户家目录下&#xff08;~&#xff09;下面有没有一个叫 test 的文件夹如果没有&#xff0c;提示按 y 创建并进入此文件夹&#xff0c;按 n 退出如果有&#xff0c;直接进入&#xff0c;提示请输入一个字符串&#xff0c;并…

Qt/C++音视频开发63-设置视频旋转角度/支持0-90-180-270度旋转/自定义旋转角度

一、前言 设置旋转角度&#xff0c;相对来说是一个比较小众的需求&#xff0c;如果视频本身带了旋转角度&#xff0c;则解码播放的时候本身就会旋转到对应的角度显示&#xff0c;比如手机上拍摄的视频一般是旋转了90度的&#xff0c;如果该视频文件放到电脑上打开&#xff0c;…

探索PyTorch优化和剪枝技术相关的api函数

torch.nn子模块Utilities解析 clip_grad_norm_ torch.nn.utils.clip_grad_norm_ 是 PyTorch 深度学习框架中的一个函数&#xff0c;它主要用于控制神经网络训练过程中的梯度爆炸问题。这个函数通过裁剪梯度的范数来防止梯度过大&#xff0c;有助于稳定训练过程。 用途 防止…

数据权限-模型简要分析

权限管控可以通俗的理解为权力限制&#xff0c;即不同的人由于拥有不同权力&#xff0c;他所看到的、能使用的可能不一样。对应到一个应用系统&#xff0c;其实就是一个用户可能拥有不同的数据权限&#xff08;看到的&#xff09;和操作权限&#xff08;使用的&#xff09;。 …

基于ssm的双减后初小教育课外学习生活活动平台的设计与实现论文

双减后初小教育课外学习生活活动平台的设计与实现 摘 要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。以前学校对于课外学习活动信息的管理和控制&#xff0c;采用人工登记的方式保存相关…

RocketMQ5-02快速部署RocketMQ5.x(手动和容器部署)

RocketMQ5快速入门指南(含部署实践) 部署环境本机单机可执行包部署、Docker部署 Mac部署&#xff1a;下载源文件可执行包部署 NameServer 问题1&#xff1a;资源不足补充: 关于日志的输出 可执行包部署 Broker 对于Local模式对于Cluster模式 对于 ProxyDocker部署 NameServerD…

AcrelEMS-BP生物制药能效管理系统——安科瑞 顾烊宇

​01 行业方案 02 项目案例 安科瑞 顾烊宇

Koodo Reader : 一个开源免费的电子书阅读器

今天在浏览 GitHub 的时候&#xff0c;偶然发现了一个非常有趣的开源项目——Koodo Reader。这个项目是一款开源免费的电子书阅读器&#xff0c;支持多种格式。它具有一些非常独特的功能&#xff0c;深深地吸引了我的注意。在接下来的内容中&#xff0c;我将为大家详细介绍一下…

oracle 12c pdb expdp/impdp 数据导入导出

环境 (源)rac 环境 byoradbrac 系统版本&#xff1a;Red Hat Enterprise Linux Server release 6.5 软件版本&#xff1a;Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit byoradb1&#xff1a;172.17.38.44 byoradb2&#xff1a;172.17.38.45 (目的&am…

升级 Vite 5 出现警告 The CJS build of Vite‘s Node API is deprecated.

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

一、二进制方式 安装部署K8S

目录 一、操作系统初始化 1、关闭防火墙 2、关闭 SELinu 3、 关闭 swap 4、添加hosts 5、同步系统时间 二、集群搭建 —— 使用外部Etcd集群 1、自签证书 2、自签 Etcd SSL 证书 ① 创建 CA 配置文件&#xff1a;ca-config.json ② 创建 CA 证书签名请求文件&#xff…

how2heap-2.23-12-house_of_spirit

house_of_spirit 注意事项 house_of_spirit&#xff1a;将一个地址伪造成符合fast bin大小的chunk&#xff0c;将其释放进fastbin中&#xff0c;同时伪造其中的fd指针&#xff0c;达到任意地址分配 伪造的chunk的大小&#xff0c;为什么是fast bin大小范围内的chunk&#xff…

将项目同时提交到GitHub和码云Gitee上面,GitHub与Gitee同步

多个远程仓库同时使用 新建GitHub仓库 创建成功 在终端中创建仓库 如果你想在本地机器上创建Git仓库&#xff0c;或者想添加一个文件夹或文件到已经存在的Git仓库中&#xff0c;你应该在终端中创建你的Git仓库。在你可以通过终端来创建一个Git仓库。以下是在终端中创建Git仓…

【基础工具篇使用】ADB 的安装和使用

文章目录 ADB的命令安装ADB 命令使用查看帮助 ——adb help查看连接设备 ADB的命令安装 ADB 命令的全称为“Android Debug Bridge”&#xff0c;从英文中看出主要是用作安卓的调试工具。ADB 命令在嵌入式开发中越来越常用了 在 Windows 上按“win”“R”组合件打开运行, 输入 …

1.框架介绍项目环境配置与项目启动!

目录 1.框架开发方向:2.项目启动与环境搭建 1.框架开发方向: 1.前后端分离项目 2.纯后端项目 3.移动端开发uni-app(ios、Android、H5、微信小程序) 4.内容管理系统2.项目启动与环境搭建 1.安装node.js 下载地址可以用nvm安装 便于运行前端项目https://blog.csdn.net/qq_58647…

【FPGA】分享一些FPGA入门学习的书籍

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

【数据结构 | 二叉树入门】

数据结构 | 二叉树入门 二叉树概念&#xff1a;二叉树特点&#xff1a;二叉树的基本形态特殊二叉树满二叉树完全二叉树 二叉树的存储结构二叉树的遍历先序遍历中序遍历后序遍历 计算二叉树的节点个数计算叶子节点的个数树的高度求第k层节点个数 二叉树概念&#xff1a; 如下图…

Vue3+TS+Vite 构建自动导入开发环境

关注⬆️⬆️⬆️⬆️ 专栏后期更新更多前端内容 在一个使用 Vue 3、Vite 和 TypeScript 的项目中,配置 unplugin-auto-import 和 unplugin-vue-components 插件可以极大地提高开发效率,因为它们可以自动导入 Vue 相关的 API 和 Vue 组件,从而减少了手动导入的需要。 文章目…

【一文详解】知识分享:(MySQL关系型数据库快速入门)

mysql基础 数据类型 整型 类型名称取值范围大小TINYINT-128〜1271个字节SMALLINT-32768〜327672个宇节MEDIUMINT-8388608〜83886073个字节INT (INTEGHR)-2147483648〜21474836474个字节BIGINT-9223372036854775808〜92233720368547758078个字节 注: 无符号在数据类型后加 un…