调用异步方法时使用.Wait()的情况是什么 [英] what are the circumstances of using .Wait() when calling async methods

查看:594
本文介绍了调用异步方法时使用.Wait()的情况是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  public async任务< ScanResult> ScanAsync(string FQDN)
{
//我正在做的操作的样本
var c = await context.SingleOrDefaultAsync(a => a.id == 1);
var list = await context.Employees.ToListAsync();
等待context.SaveChangesAsync();
// etc ..
}

我正在使用Hangfire工具支持运行后台作业来及时调用这个异步方法,但是,hangefire工具不支持直接调用异步方法。所以要克服这个问题,我创建了一个同步版本的上述方法,如下所示: -

  public void Scan()
{
ScanAsync(test)。Wait();
}

然后从HangFire调度程序调用同步方法如下: -

  RecurringJob.AddOrUpdate(()=> ss.Scan(),Cron.Minutely); 

所以我知道使用 .Wait()将主要在方法执行期间占用iis线程,但正如我所提到的,我需要这样做,因为我不能直接在hangefire调度程序中调用异步任务。



所以当我使用 .Wait()调用异步方法时会发生什么,整个方法的操作是否以同步的方式完成?例如如上所示,我在 ScanAsync(); SingleOrDefualtAsync 中有三个异步操作ToListAsync & SaveChangesAsync ,所以它们将以同步方式执行,因为我使用.wait()调用ScanAsync方法?

解决方案


所以当我使用.Wait()来调用异步方法会发生什么,
将整个方法的操作完成同步办法 ?例如
如上所示,我在ScanAsync()
中有三个异步操作; SingleOrDefualtAsync,ToListAsync& SaveChangesAsync,所以它们将以同步方式执行
,因为我使用
.wait()调用ScanAsync方法?


查询数据库的方法仍然是异步执行的,但是您调用等待的事实意味着即使您发布了该线程,它也不会返回到ASP.NET ThreadPool当您停止它。



这也是一个潜在的死锁,因为ASP.NET有一个自定义的同步上下文,确保当继续异步调用时,请求的上下文是可用的。



我建议您使用实体框架提供的同步API,因为您实际上不会享受从异步调用中获得的可扩展性



编辑:



在评论中,您问: >


由于我目前正在使用hangefire来消除异步效应?如果是,那么会更好地使用同步方法吗?或使用与hangeffire的同步或异步将是完全一样的


首先,你必须明白异步的好处。你不这么做,因为它很酷,你这样做是因为它的目的。这是什么目的?能够在负载下缩放。怎么做呢当您等待一个异步方法时,控制将返回给调用者。例如,您有一个传入请求,您可以查询数据库。您可以坐在那里等待查询完成,也可以重新使用该线程来提供更多不相同的请求。这是真正的力量。



如果你实际上没有计划收到一个体面的请求(这样你会饿死线程池),你赢了'实际上看到异步的任何好处。目前,您已实施该方案,因为您阻止异步通话,所以您将看不到任何好处。所有你会看到,可能是死锁。


I have the following async long running method inside my asp.net mvc-5 web application :-

 public async Task<ScanResult> ScanAsync(string FQDN)
 {
    // sample of the operation i am doing 
    var c = await context.SingleOrDefaultAsync(a=>a.id == 1);
    var list = await context.Employees.ToListAsync();
    await context.SaveChangesAsync();
    //etc..
}

and i am using Hangfire tool which support running background jobs to call this async method on timely basis, but un-fortuntly the hangefire tool does not support calling async methods directly . so to overcome this problem i created a sync version of the above method , as follow:-

public void Scan()
{
    ScanAsync("test").Wait();
}

then from the HangFire scheduler i am calling the sync method as follow:-

RecurringJob.AddOrUpdate(() => ss.Scan(), Cron.Minutely);

so i know that using .Wait() will mainly occupy the iis thread during the method execution ,, but as i mentioned i need to do it in this way as i can not directly call an async TASK inside the hangefire scheduler .

so what will happen when i use .Wait() to call the async method ?, will the whole method's operations be done in a sync way ? for example as shown above i have three async operations inside the ScanAsync() ;SingleOrDefualtAsync,ToListAsync & SaveChangesAsync, so will they be executed in sync way because i am calling the ScanAsync method using .wait() ?

解决方案

so what will happen when i use .Wait() to call the async method ?, will the whole method's operations be done in a sync way ? for example as shown above i have three async operations inside the ScanAsync() ;SingleOrDefualtAsync,ToListAsync & SaveChangesAsync, so will they be executed in sync way because i am calling the ScanAsync method using .wait() ?

The methods querying the database will still be executed asynchronously, but the fact that you're calling Wait means that even though you're releasing the thread, it wont return to the ASP.NET ThreadPool as you're halting it.

This is also a potential for deadlocks, as ASP.NET has a custom synchronization context which makes sure the context of the request is availiable when in a continuation of an async call.

I would recommend that instead, you'd use the synchronous API provided by entity-framework, as you won't actually be enjoying the scalability one can get from asynchronous calls.

Edit:

In the comments, you asked:

As i am currently doing with hangefire eliminate the async effect ? if yes then will it be better to use sync methods instead ? or using sync or async with hangeffire will be exactly the same

First, you have to understand what the benefits of async are. You don't do it because it's cool, you do it because it serves a purpose. What is that purpose? Being able to scale under load. How does it do that? When you await an async method, control is yielded back to the caller. For example, you have an incoming request, you query you database. You can either sit there and wait for the query to finish, or you can re-use that thread to serve more incomong requests. That's the true power.

If you don't actually plan on receiving a decent amount of requests (such that you'll starve the thread-pool), you won't actually see any benefit from async. Currently, the way you've implemented it, you won't see any of those benefits because you're blocking the async calls. All you'll see, possibly, are deadlocks.

这篇关于调用异步方法时使用.Wait()的情况是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆