Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.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#_Asynchronous_Asp.net Core_Async Await_Actionmethod - Fatal编程技术网

C# 控制器非异步方法是否阻止其他用户在使用或锁定时进入?

C# 控制器非异步方法是否阻止其他用户在使用或锁定时进入?,c#,asynchronous,asp.net-core,async-await,actionmethod,C#,Asynchronous,Asp.net Core,Async Await,Actionmethod,我有一个关于ASP.NETCore中控制器方法的新手问题。 我有下面两种不同的实现,一种是同步的,另一种是异步的 问题-我理解同步和异步之间的区别,我想,但是当涉及到输入控制器方法时,如果另一个用户在同步方法中并且仍在运行,ASP.Net会阻止所有用户输入同步方法吗 如果是这样的话,如果我预计会有成千上万的并发用户,那么这种同步方法会大大降低我的应用程序的速度,对吗 所以我应该在几乎所有地方使用异步控制器调用?除非我特别想锁定其他用户 这里是异步的 [HttpPost] publ

我有一个关于ASP.NETCore中控制器方法的新手问题。 我有下面两种不同的实现,一种是同步的,另一种是异步的

问题-我理解同步和异步之间的区别,我想,但是当涉及到输入控制器方法时,如果另一个用户在同步方法中并且仍在运行,ASP.Net会阻止所有用户输入同步方法吗

如果是这样的话,如果我预计会有成千上万的并发用户,那么这种同步方法会大大降低我的应用程序的速度,对吗

所以我应该在几乎所有地方使用异步控制器调用?除非我特别想锁定其他用户

这里是异步的

    [HttpPost]
    public async Task<IActionResult> PostRecordAsync([FromBody] Record record)
    {
        record = await RecordsContext.PostRecordAsync(_context, record);
        return Ok(record);
    }

    public static async Task<Record> PostRecordAsync(MpidDbContext context, Record record)
    {
        context.Records.Add(record);
        await context.SaveChangesAsync();
        return record;
    }

不,同步调用不会阻塞。对于web应用程序,异步方法将释放web服务器线程以响应更多请求,而以前的调用正在等待来自资源或计算密集型操作的响应

举个简单的例子。假设我有一个运行100个线程的web服务器。这意味着它可以处理100个并发请求。每个请求最多需要5秒钟才能完成,这是因为需要将请求移交给数据库进行读取和更新

对于同步调用,如果有500个活动用户访问我的web服务器,那么前100个将占用连接线程,而其余的则等待轮到他们的线程。操作完成后,下一个等待的请求将获得一个线程。请求在等待线程处理时可能会超时

对于异步调用,如果有500个活动用户访问我的web服务器,那么前100个用户将占用连接,但是当操作等待并在数据库上运行时,web服务器线程将再次可用,开始处理另一个请求。操作完成后,可以请求一个可用的web服务器线程来处理结果并最终传回响应。web服务器通过接受请求并在不等待前一个请求完成的情况下启动请求,从而有效地以响应速度更快的方式处理更多的并发请求

Async需要能够在另一个线程上恢复执行,或者在同步上下文上等待,因此会产生很小的性能成本。对于可能需要几秒钟才能运行的操作来说,这是非常值得的,但是对于可以期望总是快速完成的方法来说,这会给所有调用增加少量但不必要的性能开销。作为一般规则,我默认使用同步调用,然后引入异步,我知道处理时间将超过半秒左右。(重要的数据库调用,如
ToList
或复杂查询、文件I/O等)

在使用ASP.NETCore时,您还需要谨慎使用异步代码,因为它在没有同步上下文的情况下运行。在引用非线程安全代码(如DbContext)时使用异步的代码可能会出现多个异步调用而不轮流等待的问题


这不是最好的示例,但异步操作将在工作线程上执行,因此第二个示例将使两个上下文操作同时发生在不同的线程上。 第一个示例将在单独的线程上运行每个操作,但第二个操作仅在第一个操作完成后运行。第二个将同时运行这些操作。
除非对相同的表或相关表运行异步操作,否则可能不会出现问题。我不能具体说明这样的代码的含义,但如果在异步方法中遇到问题,则需要注意。

ASP.Net是否会阻止所有用户进入同步方法
不,这不是问题async是一种可伸缩性功能,它释放了等待IO完成的AD池线程端口,可以说它在线程资源上更轻,因此允许更大的可伸缩性,允许更多的用户,等等(松散使用的术语)在构建web应用程序时,经验法则是,如果它可以是异步的,你也可以利用它,除非有令人信服的理由不这样做(我甚至不确定我是否可以想出一个例子)ASP.NET为每个请求创建一个新的控制器对象,这样每个用户/调用方都将获得自己的类和方法来执行,而不是共享的类和方法(除非将方法声明为
static
,在这种情况下,它们共享相同的方法)。“但是异步操作将在工作线程上执行”并不完全正确。。。使用
async
的一个常见原因是简化返回原始线程以继续执行-除非代码专门设计为在工作线程上运行,否则它将在“原始”上下文(可能是也可能不是同一线程)上按顺序安排继续执行…除非采取一些特殊措施,否则您展示的示例不会为同一请求并行运行代码(DB调用将并行启动),线程行为将取决于同步上下文的存在和实现。我不能谈论EF的DBContext实现,但是如果创建由第三个方法调用的两个异步方法并在每个方法中捕获当前线程ID,则可以看到内部异步代码的线程ID彼此不同。在调用另一个线程之前,等待一个线程的仍然是不同的线程ID,但不会并行运行。在结尾处等待两者将使两者并行运行。虽然DB查询可以安全地跨线程运行,但针对本地缓存的检查和操作可能不是。。。我的评论不适用于这个问题。。。不知何故,我错过了“ASP.Net核心”中的“核心”,它实际上不再同步调用(与ASP.Net不同)-
    [HttpPost]
    public ActionResult PostRecord([FromBody] Record record)
    {
        record = RecordsContext.PostRecord(_context, record);
        return Ok(record);
    }

    public static Record PostRecord(MpidDbContext context, Record record)
    {
        context.Records.Add(record);
        context.SaveChanges();
        return record;
    }
// Should be Ok...
var product = await context.Products.SingleAsync(x => x.ProductId == productId);
var customer = await context.Customers.SingleAsync(x => x.CustomerId == customerId);
var newOrder = new Order { Product = product, Customer = customer};

// Not Ok...
var productGet = context.Products.SingleAsync(x => x.ProductId == productId);
var customerGet = context.Customers.SingleAsync(x => x.CustomerId == customerId);
var newOrder = new Order { Product = await productGet, Customer = await customerGet};