简体   繁体   中英

How to make C# method async

I've normal N tier simplified scenario below:

CONTROLLER calls BLL calls DAL

Where CONTROLLER has method below:

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

BLL has:

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

DAL has:

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.

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?

Your DAL code calls into the BLL, which is wrong.

The DAL should be using database calls, and that's the point where you start. Eg Entity Framework supports asynchronous APIs, which you call and then await . This makes your DAL methods async , so their callers (in the BLL) must await them. This makes your BLL methods async , so their callers (in the "controller") must await them. This makes your "controller" methods async .

Generally we can say, that the first calling method should be marked with async . In your case this is the WarmUp Method in the Controller.

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

Now we assume that _bll.WarUp(ID) is a long-running method. So we will refactor this method in such a way that it will return a 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. This is no problem if we do not need the return vallue of Task. But if we need it we can use the await keyword:

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. 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. At some point you need an async void method, but this is a fire-and-forget-method. Should be avoided unless you've got an event handler of some kind.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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