gpt4 book ai didi

c# - 在 .NET 中,异步方法是专门使用 async 关键字的方法吗?

转载 作者:行者123 更新时间:2023-11-30 15:14:37 25 4
gpt4 key购买 nike

我一直在学习 HttpClient(通常在 .NET 中使用 API),因此也学习了异步编程。我现在仍然很迷茫,所以试图澄清一些事情。一个我似乎找不到答案的问题 - 异步方法是否仅使用 async 关键字实现?

我知道您可以(理论上)使用异步编程创建同步方法,但您如何识别?例如,来自 this link 和这个例子:

public string GetReleases(string url)
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add(RequestConstants.UserAgent, RequestConstants.UserAgentValue);

var response = httpClient.GetStringAsync(new Uri(url)).Result;

return response;
}
}

作者说:

For the simplicity’s sake, I implemented it synchronously



但是我如何识别它是同步的?是否仅仅是因为该方法没有用 async Task 定义,例如:
public async Task<string> GetReleases(string url)

这是否意味着在 this HttpClient tutorial 中,这个例子也不是异步的:
// GET: Student
public ActionResult Index()
{
IEnumerable<StudentViewModel> students = null;

using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:64189/api/");
//HTTP GET
var responseTask = client.GetAsync("student");
responseTask.Wait();

var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var readTask = result.Content.ReadAsAsync<IList<StudentViewModel>>();
readTask.Wait();

students = readTask.Result;
}
else //web api sent error response
{
//log response status here..

students = Enumerable.Empty<StudentViewModel>();

ModelState.AddModelError(string.Empty, "Server error. Please contact administrator.");
}
}
return View(students);
}

总结一下,我的问题是:
  • 异步编程(在 .NET 中)和异步方法是否仅使用 async void/Task/Task 实现?
  • 如果不是,还有其他方法,如果是,与使用异步原理实现的同步方法相比,我如何识别“真正的”异步方法(如上面的示例?)
  • 为什么上面的例子使用“ sync through async ”,因为从我读过的所有内容来看,每个人都说永远不要这样做?它们只是不好的例子,还是为了简单起见(即便如此,不应该“正确的方法”>“简单”吗?在例如我有非常简单的代码并希望避免线程化的情况下使用它是否可以/deadlock 问题,因为我还不习惯异步编程?
  • 最佳答案

    how can I recognize truely async/sync methods?



    你不能。并不真地。您可以发现潜在的异步方法,但如果不查阅文档或这些方法的实现,就几乎无法了解其他方法。

    因此,您可以检查方法的返回类型。如果是 void ,你知道的不多。如果是 TaskTask<T>ValueTask<T> 或任何其他可等待的 type1,则该方法可能是异步的。但请记住,方法签名可能是固定的,因为该类型从基类继承了该方法,或者它正在实现一个接口(interface);因此,虽然该方法有可能是异步的,但该方法的实际实现可能是完全同步的。

    或者,该方法可能具有异步的潜力,但可能具有特定的控制流,导致其行为同步2。这些可能是例如如果某些条件为真,则该方法已经有了答案,因此它会立即返回答案。否则它会关闭并执行一些异步操作 - 作为一个例子。

    如果返回类型不可等待并且它是非空的,那么您实际上可以推断出该方法的所有原因是,在它返回时,它为该返回类型提供了一些值。没有办法推断可能已通过该方法启动的任何其他工作 - 只是如果它完成了类似的事情,它不打算让您发现该工作何时完成。

    如果您正在查看一个方法的实现并问自己“这个实现是否异步”,那么重要的是弄清楚在将控制权返回给调用者之后这段代码会发生什么。

    控制权何时返回给调用者?
  • 当我们遇到 return
  • 当我们遇到 await 时,可能是

  • 当我们点击 await 时,如果我们正在 await ing 的 awaitable 尚未完成,我们只会将控制权返回给 caller4。所以我们必须找出那个可等待的来自哪里,如果它来自调用另一个方法,我们必须重新从头开始考虑该方法的作用。

    如果该方法包含 await s,那么通常最安全的说法是它可能是异步的 - 但请记住上述关于已经完成的 awaitables 和早期的 return s 的可能性。

    如果它不是 async/ await ,它还能做什么?好吧,如果它正在使用 Task s,它可能已经创建了一个或多个这些任务来表示它正在进行的工作。它可能已经安排了更多代码通过 o​​jit_code 运行。

    如果它没有直接使用 ContinueWith s,没有调用其他可能异步的东西,没有导致创建新的 Task 并且没有不必要地混淆,那么它可能是同步的。

    Would it be ok to use this in situations where, e.g., I have very simple code and want to avoid threading/deadlock issues, since I'm not comfortable with async programming just yet?



    与使用 Thread/ async 相比,问题中示例中显示的同步异步模式更容易出现死锁。为什么?因为它们阻塞当前线程等待其他事情发生。但是它锁定的当前线程或资源可能是特殊的——它被调用的实际异步任务可能需要在它们完成之前获得对相同线程/资源的访问权限。经典的僵局。

    1Awaitable 是 C# 使用“鸭子类型”的众多地方之一。如果有一个名为 await 的可用方法(实例或扩展)返回具有正确形状的类型,则它是可等待的。因此,尽管您可能永远不会看到,但请注意,在该语言中可以自定义等待。

    2“热路径”优化浮现在脑海中。

    3和 GetAwaiter/ out参数。当然,如果它有那些它不会是通过 ref/ async 关键字实现的异步方法,但它可能仍然有一些异步行为。

    4如果我们在之前的 await 期间已经将控制权交还给调用者,那么我们不会在稍后的 await s 将控制权交还给调用者,但我们会将控制权交还给不是我们代码的“某物”。

    关于c# - 在 .NET 中,异步方法是专门使用 async 关键字的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54251841/

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