Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 异步等待的真正优势?_C#_Performance_Async Await - Fatal编程技术网

C# 异步等待的真正优势?

C# 异步等待的真正优势?,c#,performance,async-await,C#,Performance,Async Await,前面我已经发布了一个关于在客户机或服务上应用异步等待的问题。在继续这个问题之前一定要阅读这个问题,因为它与问题紧密相连 根据答案,我测试了C#4.0(TPL)和C#5.0(异步等待)的代码。我使用服务提供的方法的异步和同步版本调用服务,并比较每种情况下使用的线程数。 以下是我用来测试所用资源的代码: 主要方法 List<Task<string>> tasksList = new List<Task<string>>(); List<int&g

前面我已经发布了一个关于在客户机或服务上应用异步等待的问题。在继续这个问题之前一定要阅读这个问题,因为它与问题紧密相连

根据答案,我测试了C#4.0(TPL)和C#5.0(异步等待)的代码。我使用服务提供的方法的异步和同步版本调用服务,并比较每种情况下使用的线程数。 以下是我用来测试所用资源的代码:

主要方法

List<Task<string>> tasksList = new List<Task<string>>();
List<int> asyncThreads = new List<int>();
List<int> tplThreads = new List<int>();
Stopwatch watch = new Stopwatch();
watch.Start();

// Call the Async version of the method
for (int i = 0; i < 500; i++)
{
    tasksList.Add(GetNameFromServiceAsync("Input" + i.ToString(), asyncThreads));
}

Task.WaitAll(tasksList.ToArray());

watch.Stop();

foreach (var item in asyncThreads.Distinct())
{
    Console.WriteLine(item);
}

Console.WriteLine("(C# 5.0)Asynchrony Total Threads = " + asyncThreads.Distinct().Count());
Console.WriteLine(watch.ElapsedMilliseconds.ToString());

watch.Restart();

tasksList.Clear();

// Call the normal method
for (int i = 0; i < 500; i++)
{
    tasksList.Add(GetNameFromService("Input" + i.ToString(), tplThreads));
}

Task.WaitAll(tasksList.ToArray());

watch.Stop();

foreach (var item in tplThreads.Distinct())
{
    Console.WriteLine(item);
}

Console.WriteLine("(C# 4.0)TPL Total Threads" + tplThreads.Distinct().Count());

Console.WriteLine(watch.ElapsedMilliseconds.ToString());
List tasksList=new List();
List asynchthreads=new List();
List tplThreads=新列表();
秒表=新秒表();
watch.Start();
//调用该方法的异步版本
对于(int i=0;i<500;i++)
{
tasksList.Add(GetNameFromServiceAsync(“输入”+i.ToString(),asyncThreads));
}
Task.WaitAll(tasksList.ToArray());
看,停;
foreach(asyncThreads.Distinct()中的var项)
{
控制台写入线(项目);
}
Console.WriteLine(“(C#5.0)异步总线程数=“+asyncThreads.Distinct().Count());
Console.WriteLine(watch.elapsedmillyseconds.ToString());
watch.Restart();
tasksList.Clear();
//调用普通方法
对于(int i=0;i<500;i++)
{
tasksList.Add(GetNameFromService(“Input”+i.ToString(),tplThreads));
}
Task.WaitAll(tasksList.ToArray());
看,停;
foreach(tplThreads.Distinct()中的var项)
{
控制台写入线(项目);
}
WriteLine(((C#4.0)TPL总线程数“+tplThreads.Distinct().Count());
Console.WriteLine(watch.elapsedmillyseconds.ToString());
对服务的异步和同步调用

static async Task<string> GetNameFromServiceAsync(string name, List<int> threads)
{
  Console.WriteLine(" Start Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
    var task = await client.GetNameAsync(name);
    threads.Add(System.Threading.Thread.CurrentThread.ManagedThreadId);
   // Console.WriteLine("End GetNameFromServiceAsync Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
    return task;
}

static Task<string> GetNameFromService(string name, List<int> threads)
{

    var task = Task<string>.Factory.StartNew(() =>
        {
            threads.Add(System.Threading.Thread.CurrentThread.ManagedThreadId);
         //   Console.WriteLine("GetNameFromService Current Thread : " + System.Threading.Thread.CurrentThread.ManagedThreadId);
            return client.GetName(name);
        });

    return task;
}
静态异步任务GetNameFromServiceAsync(字符串名称,列出线程)
{
WriteLine(“启动当前线程:+System.Threading.Thread.CurrentThread.ManagedThreadId”);
var task=await client.GetNameAsync(name);
添加(System.Threading.Thread.CurrentThread.ManagedThreadId);
//Console.WriteLine(“End GetNameFromServiceAsync当前线程:+System.Threading.Thread.CurrentThread.ManagedThreadId”);
返回任务;
}
静态任务GetNameFromService(字符串名称,列表线程)
{
var task=task.Factory.StartNew(()=>
{
添加(System.Threading.Thread.CurrentThread.ManagedThreadId);
//WriteLine(“GetNameFromService当前线程:+System.Threading.Thread.CurrentThread.ManagedThreadId”);
返回client.GetName(name);
});
返回任务;
}
现在,我已经找到了答案,并得出了以下结果:

  • 如果我对该服务进行500次调用,它只使用4-5个线程
  • TPL调用产生大约44-45个线程
  • 异步调用的时间约为17-18秒
  • 第三方物流的通话时间约为42-45秒
我想对我的发现有一些反馈,以便对其他社区成员也有用。这是我先前问题的答案吗

编辑

我的观察结论是,如果我们使用Async Await而不是TPL的Task.Factory.startNew,那么它将消耗更少的线程。这有多正确?如果没有,那么进行这种比较的正确方向是什么


在我学习async-await的过程中,我想通过某种比较和可靠的代码来证明它的价值。

客户端
async
(与同步代码相比)通常会提高响应速度,但内存成本很低

服务器端
async
(与同步代码相比)通常通过减少内存/线程使用来提高可伸缩性。这些优点也适用于客户端
async
(与多线程代码相比)

这两个都是极端的概括,当然也有一些情况是错误的

更新:

我的观察得出结论,如果我们使用Async Wait…,那么它将消耗更少的线程

异步
/
等待
启用可维护的异步代码。它们本身与创建线程无关。但是,它们通常与
Task.Run
(或
Task.Factory.StartNew
)一起使用以创建后台任务

在我学习async-await时,我想通过某种比较和可靠的代码来证明它的价值

async
await
是编译器转换。它们使编写异步程序变得更容易——仅此而已


如果将它们与同步代码进行比较,您通常会看到响应性和/或可伸缩性有所提高。如果您将它们与现有的异步代码进行比较,那么它们的效率通常会稍低一些,但在代码可维护性方面却远远弥补了这一点。

您的问题到底是什么?通过使用async-Wait,我们可以获得内存优势(使用的资源更少)。这是我从前面的问题中得到的,或者我理解的,我想知道这就是答案。我想问一下使用async await的可伸缩性优势。这与我的结论一致吗?一个重要的优势是,用户在编写同步代码时不能说他们遇到了异步问题。微基准测试通常很难评估这样的问题,IMHO。谢谢stephen。我已经更新了我的问题。