简体   繁体   English

如何使C#方法异步

[英]How to make C# method async

I've normal N tier simplified scenario below: 我在下面是正常的N层简化方案:

CONTROLLER calls BLL calls DAL 控制器呼叫BLL呼叫DAL

Where CONTROLLER has method below: CONTROLLER具有以下方法:

public void WarmUp()
{
    var bll=_bll.WarmUp(ID);
}

BLL has: BLL具有:

public bool WarmUp()
{
    return_dal.WarmUp(ID);
}

DAL has: DAL具有:

public bool FetchData()
{
    var dal=_bll.WarmUp(ID);
    if(dal !=null)
     {return true;}
    else{return false;}
}

Now, what I like to do is make the BLL and DAL methods (not sure if both has to be async ) to be ASYNC such that after CONTROLLER invokes, it doesn't block the thread. 现在,我想做的是使BLL和DAL方法(不确定是否必须都是async )成为ASYNC,以便在CONTROLLER调用后,它不会阻塞线程。

I've not done Task based programming yet. 我还没有完成基于任务的编程。 Could someone please help me convert the above code(BLL/DLL) to be async (c# async await) so that they are asynchronous? 有人可以帮我将上述代码(BLL / DLL)转换为异步代码(c#async await),以使它们异步吗?

Your DAL code calls into the BLL, which is wrong. 您的DAL代码调用了BLL,这是错误的。

The DAL should be using database calls, and that's the point where you start. DAL应该使用数据库调用,这就是开始的地方。 Eg Entity Framework supports asynchronous APIs, which you call and then await . 例如,实体框架支持异步API,您可以调用它们,然后再await This makes your DAL methods async , so their callers (in the BLL) must await them. 这使您的DAL方法async ,因此它们的调用方(在BLL中)必须await它们。 This makes your BLL methods async , so their callers (in the "controller") must await them. 这使您的BLL方法async ,因此它们的调用者(在“控制器”中)必须await它们。 This makes your "controller" methods async . 这使您的“控制器”方法async

Generally we can say, that the first calling method should be marked with async . 通常,我们可以说,第一个调用方法应标记为async In your case this is the WarmUp Method in the Controller. 您的情况是控制器中的WarmUp方法。

public async void WarmUp()
{
    var bll=_bll.WarmUp(ID);
}

Now we assume that _bll.WarUp(ID) is a long-running method. 现在,我们假定_bll.WarUp(ID)是一个长期运行的方法。 So we will refactor this method in such a way that it will return a Task 因此,我们将以某种方式重构此方法,使其返回Task

public Task<bool> WarmUp()
{
    return Task.Run(()=>{_dal.WarmUp(ID);});
}

But this will not solve our problem, because now we have the case that if we call the Controller method we will immediately return. 但这并不能解决我们的问题,因为现在有了这种情况,如果调用Controller方法,我们将立即返回。 This is no problem if we do not need the return vallue of Task. 如果我们不需要Task的返回值,这没问题。 But if we need it we can use the await keyword: 但是,如果需要,我们可以使用await关键字:

public async void WarmUp()
{
    var bll= await _bll.WarmUp(ID);
    if(bll)
    {
        //do whatever you want
    }
}

How about this: 这个怎么样:

public Task<bool> FetchData()
{
    var tcs = new TaskCompletionSource<bool>();
    Task.Run(() => {
        var dal=_bll.WarmUp(ID);    
        tcs.SetResult(dal != null);
    });

    return tcs.Task.Result;
}

TaskCompletionSource is good for making something not async to become async'able. TaskCompletionSource可以使不异步的东西变得异步。 Then you can just await the calls up until your last layer 然后,您可以等待通话,直到最后一层

public async Task<bool> WarmUp()
{
    return await _dal.WarmUp(ID);
}

This could be your GUI button callback. 这可能是您的GUI按钮回调。 At some point you need an async void method, but this is a fire-and-forget-method. 在某些时候,您需要一个异步void方法,但这是一种“一劳永逸”的方法。 Should be avoided unless you've got an event handler of some kind. 除非您有某种事件处理程序,否则应避免使用。

public async void WarmUp()
{
    var bll= await _bll.WarmUp(ID);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM