Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async behaving sync while debugging?

Something is definitely flawed in my understanding of async/await. I want a piece of code named SaveSearchCase to run asynchronously in background.

I want it to be fired and forget about it and continue with the current method's return statement.

public IList<Entities.Case.CreateCaseOutput> createCase(ARC.Donor.Data.Entities.Case.CreateCaseInput CreateCaseInput, ARC.Donor.Data.Entities.Case.SaveCaseSearchInput SaveCaseSearchInput)
{
    ..........
    ..........
    ..........
    var AcctLst = rep.ExecuteStoredProcedure<Entities.Case.CreateCaseOutput>(strSPQuery, listParam).ToList();

    if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString()))
    {
        Task<IList<Entities.Case.SaveCaseSearchOutput>> task = saveCaseSearch(SaveCaseSearchInput, AcctLst.ElementAt(0).o_case_seq);
        Task t = task.ContinueWith(
                r => { Console.WriteLine(r.Result); }
         );
    }
    Console.WriteLine("After the async call");
    return AcctLst;
}

And the SaveCaseSearch looks like

public async Task<IList<Entities.Case.SaveCaseSearchOutput>> saveCaseSearch(ARC.Donor.Data.Entities.Case.SaveCaseSearchInput SaveCaseSearchInput,Int64? case_key)
{
    Repository rep = new Repository();
    string strSPQuery = string.Empty;
    List<object> listParam = new List<object>();
    SQL.CaseSQL.getSaveCaseSearchParameters(SaveCaseSearchInput, case_key,out strSPQuery, out listParam);
    var AcctLst = await rep.ExecuteStoredProcedureAsync<Entities.Case.SaveCaseSearchOutput>(strSPQuery, listParam);
    return (System.Collections.Generic.IList<ARC.Donor.Data.Entities.Case.SaveCaseSearchOutput>)AcctLst;
}

But when I see the debugger createCase method waits for SaveCaseSearch to complete first and then only

it prints "After Async Call "

and then returns . Which I do not want definitely .

So which way is my understanding flawed ? Please help to make it run async and continue with current method's print and return statement .

UPDATE

I updated the SaveCaseSearch method to reflect like :

public async Task<IList<Entities.Case.SaveCaseSearchOutput>> saveCaseSearch(ARC.Donor.Data.Entities.Case.SaveCaseSearchInput SaveCaseSearchInput,Int64? case_key)
{
    return Task.Run<IList<Entities.Case.SaveCaseSearchOutput>>(async (SaveCaseSearchInput, case_key) =>
    {
        Repository rep = new Repository();
        string strSPQuery = string.Empty;
        List<object> listParam = new List<object>();
        SQL.CaseSQL.getSaveCaseSearchParameters(SaveCaseSearchInput, case_key, out strSPQuery, out listParam);
        var AcctLst = await rep.ExecuteStoredProcedureAsync<Entities.Case.SaveCaseSearchOutput>(strSPQuery, listParam);
        return (System.Collections.Generic.IList<ARC.Donor.Data.Entities.Case.SaveCaseSearchOutput>)AcctLst;
    });
}

But there is something wrong with the params. It says

Error   4   A local variable named 'SaveCaseSearchInput' cannot be declared in this scope because it would give a different meaning to 'SaveCaseSearchInput', which is already used in a 'parent or current' scope to denote something else C:\Users\m1034699\Desktop\Stuart_V2_12042016\Stuart Web Service\ARC.Donor.Data\Case\Search.cs   43  79  ARC.Donor.Data
like image 755
StrugglingCoder Avatar asked Dec 12 '25 09:12

StrugglingCoder


1 Answers

Well this saveCaseSearch() method runs synchronously in main thread and this is the main problem here. Instead of returning result with a task you should return Task with operation itself. Here is some simplified example :

Runs synchronously and waits 5 seconds

    public IList<int> A()
    {

        var AcctLst = new List<int> { 0, 2, 5, 8 };

        if (true)
        {
            Task<IList<int>> task = saveCaseSearch();

            Task t = task.ContinueWith(
                    r => { Console.WriteLine(r.Result[0]); }
             );
        }

        Console.WriteLine("After the async call");

        return AcctLst;
    }

    // runs sync and in the end returns Task that is never actually fired
    public async Task<IList<int>> saveCaseSearch()
    {
        Thread.Sleep(5000);
        return new List<int>() { 10, 12, 16 };
    }

Runs asynchronously - fires task & forgets :

    public IList<int> A()
    {
        ... same code as above
    }

    // notice that we removed `async` keyword here because we just return task.
    public Task<IList<int>> saveCaseSearch()
    {
        return Task.Run<IList<int>>(() =>
        {
            Thread.Sleep(5000);
            return new List<int>() { 10, 12, 16 };
        });
    }

Here is full code for this example

like image 130
Fabjan Avatar answered Dec 14 '25 23:12

Fabjan