gpt4 book ai didi

c# - 想了解异步

转载 作者:太空狗 更新时间:2023-10-29 17:39:07 24 4
gpt4 key购买 nike

我已经使用了一点异步编码,但我并没有真正完全理解如何使用它——尽管我理解这个概念以及我为什么需要它。

这是我的设置:

我有一个 Web API,我将从我的 ASP.NET MVC 应用程序调用它,我的 Web API 将调用 DocumentDB。在代码示例中,我在向 DocumentDB 发送查询时看到了很多 await 关键字。

如果我需要在我的 MVC 应用程序中使我的 Index 操作方法异步,我会感到困惑吗?如果我的 Web API 中的 CreateEmployee() 方法应该是异步的,我也很困惑?

在这种情况下使用异步的正确方法是什么?

这是我的代码(这段代码目前给我错误,因为我的 MVC 操作方法不是异步的)---- ASP.NET MVC 应用程序代码 ----

public ActionResult Index()
{

Employee emp = new Employee();
emp.FirstName = "John";
emp.LastName = "Doe";
emp.Gender = "M";
emp.Ssn = "123-45-6789";

using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://myWebApi.com");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

HttpResponseMessage response = await client.PostAsJsonAsync("hr/create/newemployee", emp);
if (response.IsSuccessStatusCode)
{
emp = await response.Content.ReadAsAsync<Employee>();
}
}

// Display employee info
return View(emp);
}

---- Web API 代码----

private static readonly string endPointUrl = ConfigurationManager.AppSettings["EndPointUrl"];
private static readonly string authorizationKey = ConfigurationManager.AppSettings["AuthorizationKey"];
private static readonly string databaseId = ConfigurationManager.AppSettings["DatabaseId"];
private static DocumentClient client;

public static async Task<Employee> CreateEmployee(Employee emp)
{
try
{
//Create a Document client
using (client = new DocumentClient(new Uri(endPointUrl), authorizationKey))
{
//Get the database
var database = await GetDatabaseAsync();

//Get the Document Collection
var collection = await GetCollectionAsync(database.SelfLink, "Employees");

await client.CreateDocumentAsync(collection.SelfLink, emp);

// Further process employee
}
}
catch
{
// Handle error
}

return employee;
}

private static async Task<DocumentCollection> GetCollectionAsync(string dbLink, string id)
{
DocumentCollection collection = client.CreateDocumentCollectionQuery(dbLink).Where(c => c.Id == id).ToArray().FirstOrDefault();

return collection;
}

private static async Task<Database> GetDatabaseAsync()
{
Database database = client.CreateDatabaseQuery().Where(db => db.Id == databaseId).ToArray().FirstOrDefault();

return database;
}

最佳答案

这是我的解释

class MainClass
{
public static async Task<String> AsyncMethod(int delay) {

await Task.Delay (TimeSpan.FromSeconds(delay));

return "The method has finished it's execution after waiting for " + delay + " seconds";
}

public static async Task Approach1(int delay)
{
var response = await AsyncMethod (delay); // await just unwraps Task's result

Console.WriteLine (response);
}

public static Task Approach2(int delay)
{
return AsyncMethod(delay).ContinueWith(message => Console.WriteLine(message)); // you could do the same with
}

public static void Main (string[] args)
{
var operation1 = Approach1 (3);
var operation2 = Approach2 (5);

Task.WaitAll (operation1, operation2);

Console.WriteLine("All operations are completed")
}
}

最终 Approach1Approach2 是相同的代码段。

async/await 是任务 API 的语法糖。它需要您的 async 方法将其拆分为 await 之前和 await 之后的部分。 “之前”部分立即执行。当 await 操作完成时,将执行“after”部分。由于您获得了对任务的引用,因此您可以通过任务 API 跟踪操作的第二部分。

通常,async 允许将方法调用视为某种长操作,您可以通过任务 API 引用它并等待它完成并继续另一段代码。通过 ContinueWith 调用或通过使用 await 通常都是一样的。

async/await/Task 概念之前,人们使用回调,但处理错误非常容易,Task 类似于 callback 的概念,除了它能够更容易地处理异常。

一般来说,所有这些 Task/async/await 咒语都接近于 promises 的概念,如果你碰巧使用过 jQuery/JavaScript,那么这里有一个类似的概念,这是一个很好的问题,解释了它是如何完成的有“jQuery deferreds and promises - .then() vs .done()


编辑:我刚刚发现 .NET 缺少类似于 jQuery/JavaScript 中的then 功能的实现。

ContinueWithThen 的区别在于 Then 可以组合任务,并在 ContinueWith 不是,它只能并行启动任务,但可以通过 await 构造轻松实现。这是包含整个 shebang 的更新代码:

static class Extensions
{
// Implementation to jQuery-like `then` function in .NET
// According to: http://blogs.msdn.com/b/pfxteam/archive/2012/08/15/implementing-then-with-await.aspx
// Further reading: http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx
public static async Task Then(this Task task, Func<Task> continuation)
{
await task;
await continuation();
}

public static async Task<TNewResult> Then<TNewResult>(
this Task task, Func<Task<TNewResult>> continuation)
{
await task;
return await continuation();
}

public static async Task Then<TResult>(
this Task<TResult> task, Func<TResult,Task> continuation)
{
await continuation(await task);
}

public static async Task<TNewResult> Then<TResult, TNewResult>(
this Task<TResult> task, Func<TResult, Task<TNewResult>> continuation)
{
return await continuation(await task);
}
}

class MainClass
{
public static async Task<String> AsyncMethod1(int delay) {

await Task.Delay (TimeSpan.FromSeconds(delay));

return "The method has finished it's execution after waiting for " + delay + " seconds";
}

public static Task<String> AsyncMethod2(int delay)
{
return Task.Delay (TimeSpan.FromSeconds (delay)).ContinueWith ((x) => "The method has finished it's execution after waiting for " + delay + " seconds");
}

public static async Task<String> Approach1(int delay)
{
var response = await AsyncMethod1 (delay); // await just unwraps Task's result

return "Here is the result of AsyncMethod1 operation: '" + response + "'";
}

public static Task<String> Approach2(int delay)
{
return AsyncMethod2(delay).ContinueWith(message => "Here is the result of AsyncMethod2 operation: '" + message.Result + "'");
}

public static void Main (string[] args)
{
// You have long running operations that doesn't block current thread
var operation1 = Approach1 (3); // So as soon as the code hits "await" the method will exit and you will have a "operation1" assigned with a task that finishes as soon as delay is finished
var operation2 = Approach2 (5); // The same way you initiate the second long-running operation. The method also returns as soon as it hits "await"

// You can create chains of operations:
var operation3 = operation1.ContinueWith(operation1Task=>Console.WriteLine("Operation 3 has received the following input from operation 1: '" + operation1Task.Result + "'"));
var operation4 = operation2.ContinueWith(operation2Task=>Console.WriteLine("Operation 4 has received the following input from operation 2: '" + operation2Task.Result + "'"));

var operation5 = Task.WhenAll (operation3, operation4)
.Then(()=>Task.Delay (TimeSpan.FromSeconds (7)))
.ContinueWith((task)=>Console.WriteLine("After operation3 and 4 have finished, I've waited for additional seven seconds, then retuned this message"));

Task.WaitAll (operation1, operation2); // This call will block current thread;

operation3.Wait (); // This call will block current thread;
operation4.Wait (); // This call will block current thread;
operation5.Wait (); // This call will block current thread;

Console.WriteLine ("All operations are completed");
}
}

关于c# - 想了解异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27116794/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com