> 馆藏中心

如何使用 C# 中的 ValueTask

来源:OSCHINA 编辑:吕秀强

你应当注明2113是C51,否则会误导很多计5261算机的朋友。4102看你想1653实现什么样的功版能。unsigned char code table[];分配一个指权向code区的指针,指针本身在默认存储区。code unsigned char table[];分配一个指向默认存储区的指针,指针本身在code区。Keil的说明书里面都写得非常明白www.179s.com防采集请勿采集本网。

在 C# 中利用 ValueTask 避免从异步方法返回 Task 对象时分配

翻译自 Joydip Kanjilal 2020年7月6日 的文章 《How to use ValueTask in C#》
异步编程已经使用了相当长一段时间了。近年来,随着 async 和 await 关键字的引入,它变得更加强大。您可以利用异步编程来提高应用程序的响应能力和吞吐量。C# 中异步方法的推荐返回类型是 Task。如果您想编写一个有返回值的异步方法,那么应该返回 Task<T>; 如果想编写事件处理程序,则可以返回 void。在 C# 7.0 之前,异步方法可以返回 TaskTask<T> 或 void。从 C# 7.0 开始,异步方法还可以返回 ValueTask(作为 System.Threading.Tasks.Extensions 包的一部分可用)或 ValueTask<T>。本文就讨论一下如何在 C# 中使用 ValueTask。要使用本文提供的代码示例,您的系统中需要安装 Visual Studio 2019。如果还没有安装,您可以在这里下载 Visual Studio 2019。

在 Visual Studio 中创建一个 .NET Core 控制台应用程序项目

首先,让我们在 Visual Studio 中创建一个 .NET Core 控制台应用程序项目。假设您的系统中安装了 Visual Studio 2019,请按照下面描述的步骤在 Visual Studio 中创建一个新的 .NET Core 控制台应用程序项目。
  1. 启动 Visual Studio IDE。
  2. 点击 “创建新项目”。
  3. 在 “创建新项目” 窗口中,从显示的模板列表中选择 “控制台应用(.NET Core)”。
  4. 点击 “下一步”。
  5. 在接下来显示的 “配置新项目” 窗口,指定新项目的名称和位置。
  6. 点击 “创建”。
这将在 Visual Studio 2019 中创建一个新的 .NET Core 控制台应用程序项目。我们将在本文后面的部分中使用这个项目来说明 ValueTask 的用法。

为什么要使用 ValueTask ?

Task 表示某个操作的状态,即此操作是否完成、取消等。异步方法可以返回 Task 或者 ValueTask。现在,由于 Task 是一个引用类型,从异步方法返回一个 Task 对象意味着每次调用该方法时都会在托管堆(managed heap)上分配该对象。因此,在使用 Task 时需要注意的一点是,每次从方法返回 Task 对象时都需要在托管堆中分配内存。如果你的方法执行的操作的结果立即可用或同步完成,则不需要这种分配,因此代价很高。这正是 ValueTask 要出手相助的目的,ValueTask<T> 提供了两个主要好处。首先,ValueTask<T> 提高了性能,因为它不需要在堆(heap)中分配; 其次,它的实现既简单又灵活。当结果立即可用时,通过从异步方法返回 ValueTask<T> 代替 Task<T>,你可以避免不必要的分配开销,因为这里的 “T” 表示一个结构,而 C# 中的结构体(struct)是一个值类型(与 Task<T> 中表示类的 “T” 不同)。C# 中 Task 和 ValueTask 表示两种主要的 “可等待(awaitable)” 类型。请注意,您不能阻塞(block)一个 ValueTask。如果需要阻塞,则应使用 AsTask 方法将 ValueTask 转换为 Task,然后在该引用 Task 对象上进行阻塞。另外请注意,每个 ValueTask 只能被消费(consumed)一次。这里的单词 “消费(consume)” 是指 ValueTask 可以异步等待(await)操作完成,或者利用 AsTask 将 ValueTask 转换为 Task。但是,ValueTask 只应被消费(consumed)一次,之后 ValueTask<T> 应被忽略。

C# 中的 ValueTask 示例

假设有一个异步方法返回一个 Task。你可以利用 Task.FromResult 创建 Task 对象,如下面给出的代码片段所示。

public Task<int> GetCustomerIdAsync() {     return Task.FromResult(1); }上面的代码片段并没有创建整个异步状态机制,但它在托管堆(managed heap)中分配了一个 Task 对象。为了避免这种分配,您可能希望利用 ValueTask 代替,像下面给出的代码片段所示的那样。

在源文件A1.c中调用A2.c 中的函数有两种方法: 1、在A2.c中有完整的函数定义,在A1.c中添加一下要用到的函数原型(声明)就可以了,例如: 在A2.c中:有函数void A2(){};。 在A1.c中:在文件前头增加一行:void A2();就可以了。 2、把A2.c中

public ValueTask<int> GetCustomerIdAsync() {     return new ValueTask<int>(1); }下面的代码片段演示了 ValueTask 的同步实现。

1、C语言中,有两个log函数,分别为log10和log函数,具体用法如下: 2、函数名: log10 功 能: 对数函数log,以10为底 用 法: double log10(double x); 程序示例: #include #include int main(void) { double result; double x = 800.6872; result

public interface IRepository<T> {     ValueTask<T> GetData(); }Repository 类扩展了 IRepository 接口,并实现了如下所示的方法。

函数名: mkdir 功 能: 建立一个目录(文件夹) 用 法: int mkdir(char *pathname); 程序例: (在win-tc和Dev-c++下运行通过) #include #include #include int main(void) { int status; system("cls"); status = mkdir("book"); /*这是在程序所在

public class Repository<T> : IRepository<T> {     public ValueTask<T> GetData()     {         var value = default(T);         return new ValueTask<T>(value);     } }下面是如何从 Main 方法调用 GetData 方法。

要在java中调用c语言的库,需要使用Java提供了JNI。 举例说明 在c语言中定义一个 void sayHello()函数(打印Hello World);然后在Java中调用这个函数显示Hello Word. 现在分别从Java和C语言两部分说明: 1. Java 部分 首先定义一个HelloNative,在其

static void Main(string[] args) {     IRepository<int> repository = new Repository<int>();     var result = repository.GetData();     if (result.IsCompleted)         Console.WriteLine("Operation complete...");     else         Console.WriteLine("Operation incomplete...");     Console.ReadKey(); }现在让我们将另一个方法添加到我们的存储库(repository)中,这次是一个名为 GetDataAsync 的异步方法。以下是修改后的 IRepository 接口的样子。

//声明 #include #include #include #include #include #define SIZE 4 static int score=0; void putn(int n[][SIZE]); void getn(int n[][SIZE]); int isempty(int n[][SIZE]); int isfull(int n[][SIZE]); void math(int n[][SIZE],char c);

public interface IRepository<T> {     ValueTask<T> GetData();      ValueTask<T> GetDataAsync(); }GetDataAsync 方法由 Repository 类实现,如下面给出的代码片段所示。

public class Repository<T> : IRepository<T> {     public ValueTask<T> GetData()     {         var value = default(T);         return new ValueTask<T>(value);     }      public async ValueTask<T> GetDataAsync()     {         var value = default(T);         await Task.Delay(100);         return value;     } }

C# 中应该在什么时候使用 ValueTask ?

尽管 ValueTask 提供了一些好处,但是使用 ValueTask 代替 Task 有一定的权衡。ValueTask 是具有两个字段的值类型,而 Task 是具有单个字段的引用类型。因此,使用 ValueTask 意味着要处理更多的数据,因为方法调用将返回两个数据字段而不是一个。另外,如果您等待(await)一个返回 ValueTask 的方法,那么该异步方法的状态机也会更大,因为它必须容纳一个包含两个字段的结构体而不是在使用 Task 时的单个引用。此外,如果异步方法的使用者使用 Task.WhenAll 或者 Task.WhenAny,在异步方法中使用 ValueTask<T> 作为返回类型可能会代价很高。这是因为您需要使用 AsTask 方法将 ValueTask<T> 转换为 Task<T>,这会引发一个分配,而如果使用起初缓存的 Task<T>,则可以轻松避免这种分配。经验法则是这样的:当您有一段代码总是异步的时,即当操作(总是)不能立即完成时,请使用 Task。当异步操作的结果已经可用时,或者当您已经缓存了结果时,请利用 ValueTask。不管怎样,在考虑使用 ValueTask 之前,您都应该执行必要的性能分析。

goto语句使用:1、C#语言中32313133353236313431303231363533e58685e5aeb931333431353432using System;using static System.Console;class Program{public static Int32 Main(String[]args){int n=0;WriteLine("input a string:\n");loop:if(Read()!='\r'){n++;goto loop;}WriteLine("{0}",n);return 0;}}2、C语言中统计从键盘输入一行字符的个数。#include&lt;stdio.h&gt;int n=0;int main(void){printf("input a string:");loop:if(getchar()!='\n'){n++;goto loop;}printf("output:%d\n",n);}例如输入:abcdefghijklmnopqrstuvwxyz然后回车Enter输出:26本例用if语句和goto语句构成循环结构。当输入字符不为'\n'时即执行n++进行计数。然后转移至if语句循环执行,直至输入字符为'\n'才停止循环。3、汇编语言中goto语句与汇编语言里面的jmp指令相同,(无条件转移)1+2+3........+8+9+10NASM描述:mov ax,1mov bx,0start:add bx,axinc axcmp ax,11;比较指令jzend;零转移jmp startend:;;start:end:是标号Pascal格式goto&lt;标号&gt;;其中标号需要申请,在程序开头写label&lt;标号1&gt;,&lt;标号2&gt;,……;其中,标号必须为四位以内的正整数。在该段落内还需要有&lt;标号&gt;:语句表示将要转向的方向。4、delphi中//Goto语句用在跳转行号,可以跳转到当前结构层内任意位置.//必须在声明处用label关键字声明行号.//由于Goto语句会破坏程序的结构,不推荐使用.vara,b:Integer;labelX,Y;beginif a&gt;b thengoto Xelsegoto Y;X:WriteLn('a&gt;b');Y:WriteLn('b&gt;a');end;扩展资料:goto语句无条件转移语句,其一般格式如下:goto语句标号;其中语句标号是按标识符规定书写的符号,放在某一语句行的前面,标号后加冒号(:)。语句标号起标识语句的作用,与goto语句配合使用。如:label:i++;loop:while(x&lt;7);goto:loopC语言不限制程序中使用标号的次数,但各标号不得重名。goto语句的语义是改变程序流向,转去执行语句标号所标识的语句。goto语句通常与条件语句配合使用。可用来实现条件转移,构成循环,跳出循环体等功能。但是,在结构化程序设计中一般不主张使用goto语句,以免造成程序流程的混乱,使理解和调试程序都产生困难。参考资料来源:百度百科——goto语句,goto语句袭也称为无条件2113转移语句,其一般格式如5261下: goto 语句标4102号; 其中语句标号是按标识符规定1653书写的符号, 放在某一语句行的前面,标号后加冒号(:)。语句标号起标识语句的作用,与goto 语句配合使用。#include"stdio.h"int main(void){    int n=0;    printf("input a string :\n");    loop: if(getchar()!='\n')        {            n++;            goto loop;        }    printf("%d",n);}goto语句在上例中的作用就是当接收用户输入的字符不是回车符的时候就跳转到if语句进行判断用户输入的字符,也就是说如果用户输入回车,那么就输入结束,转而执行printf("%d",n);,要回到哪里,2113就在哪里加个5261标号,例如:label1: /* <----- 这里4102加1653个标号专, goto 语句就可以转到这里了属 */switch(i){case 1:ex(0);goto label1; /* 有 goto 就不需要 break 了 */另,使用goto语句需要加特殊的抬头。本回答被提问者采纳,要完成你要求的功能,只需要把main里面你处理的那一段用一个while(1){}包含就可以了,goto已经是过去时了,不要专研了,以后用的人也会少了内容来自www.179s.com请勿采集。

本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。本文《如何使用 C# 中的 ValueTask》转载自OSCHINA,版权归原作者所有,若侵权请联系:E-MAIL:513175919@qq.com
违法违规信息请立即联系本网可获得现金奖励,TEL:1-8-2-1-0-2-3-3-3-8-1(电话仅供违法违规信息举报,侵权类信息请EMAIL。)

www.179s.com false 互联网 http://www.179s.com/itpubblogs/69983768/2723774.html report 12408 在 C# 中利用 ValueTask 避免从异步方法返回 Task 对象时分配翻译自 Joydip Kanjilal 2020年

热门图片

经济金融企业管理法律法规社会民生科学教育降生活体育运动文化艺术电子数码电脑网络娱乐休闲行政地区心理分析医疗卫生