2016-04-13 81 views
3

我对异步/等待的理解肯定有缺陷。我想要一段名为SaveSearchCase的代码在后台异步运行。异步在调试时表现同步?

我希望它被解雇并忘记它,并继续使用当前方法的return语句。

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; 
} 

而且SaveCaseSearch看起来像

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; 
} 

但是,当我看到调试器createCase方法等待SaveCaseSearch完成第一,然后只

它打印“异步调用后”

然后返回。我不想确定。

那么我的理解哪种方式有缺陷?请帮助使其运行异步并继续使用当前方法的打印返回语句

UPDATE

我更新了SaveCaseSearch方法来反映,如:

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; 
    }); 
} 

但也有一些是错误的PARAMS。它说

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 
+0

当您使用异步功能,你应该通过回调到您的函数,它做的所有事情之后,你需要你调用回调这是你如何使用异步,因为当你使用回statment它将如果运行同步 –

+0

(!字符串.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString())) {SaveCaseSearch ...} 我想在后台异步调用此方法。你能告诉我如何达到相同的目的吗? – StrugglingCoder

+0

调用'saveCaseSearch'方法时应使用await关键字,然后打印结果。 – Hendry

回答

2

嗯,这saveCaseSearch()方法在主线程同步运行,在这里,这是主要问题。不要用任务返回结果,而应该用操作本身返回任务。下面是一些简化的例子:

奔跑同步,并且等待5秒

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 }; 
    } 

异步运行 - 火灾任务&忘记:

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 }; 
     }); 
    } 

这里是full code for this example

+0

实际上在SaveCaseSearch的代码中,我们有类似于 的东西等待rep.ExecuteStoredProcedureAsync (strSPQuery,listParam); 它是好的然后包装一切由Task.Run <>()?即可以等待Task.Run <>()? – StrugglingCoder

+0

@StrugglingCoder是的,你可以在任务内添加'async'关键字,例如:Task.Run >(* async *()=> {});' – Fabjan

+0

@StrugglingCoder这看起来像不同的问题,请问或用新的代码和问题更新你的问题 – Fabjan

0

出乎所有人的,我相信在有关“发射后不管”你可以做到这一点通过编写代码是这样的:

public Task<SaveCaseSearchOutput> SaveCaseSearch(
    SaveCaseSearchInput saveCaseSearchInput, 
    long? caseKey) 
{ 
    var rep = new Repository(); 
    var query = string.Empty; 
    var listParam = new List<object>(); 
    SQL.CaseSQL 
     .getSaveCaseSearchParameters(
      saveCaseSearchInput, 
      caseKey, 
      out query, 
      out listParam); 

    return rep.ExecuteStoredProcedureAsync<SaveCaseSearchOutput>(
     strSPQuery, 
     istParam); 
} 

然后,如果,你想的地方火了和日志,当它返回(这是真的,你有什么 - 这样你就不会忘记这件事),这样做:

public IList<CreateCaseOutput> CreateCase(
    CreateCaseInput createCaseInput, 
    SaveCaseSearchInput saveCaseSearchInput) 
{ 
    // Omitted for brevity... 

    var AcctLst = 
     rep.ExecuteStoredProcedure<CreateCaseOutput>(
      strSPQuery, 
      listParam) 
      .ToList(); 

    if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString())) 
    { 
     SaveCaseSearch(saveCaseSearchInput, 
         AcctLst.ElementAt(0).o_case_seq) 
      .ContinueWith(r => Console.WriteLine(r.Result)); 
    } 

    Console.WriteLine("After the async call"); 
    return AcctLst; 
} 

的问题是,你是在SaveSearchCase功能使用asyncawait,和这个基地lly意味着你的代码与“随时忘却”相反。


作为一个侧面说明,你应该只使用asyncawait,并避免“发射后不管”的想法!让你的数据库调用异步,并利用这个范例来证明它的价值!

考虑以下几点:

SaveCaseSearch呼叫可以留下,因为我已经在上面定义了它。

public Task<SaveCaseSearchOutput> SaveCaseSearch(
    SaveCaseSearchInput saveCaseSearchInput, 
    long? caseKey) 
{ 
    var rep = new Repository(); 
    var query = string.Empty; 
    var listParam = new List<object>(); 
    SQL.CaseSQL 
     .getSaveCaseSearchParameters(
      saveCaseSearchInput, 
      caseKey, 
      out query, 
      out listParam); 

    return rep.ExecuteStoredProcedureAsync<SaveCaseSearchOutput>(
     strSPQuery, 
     istParam); 
} 

然后在你调用它,而是执行此操作:

public async Task<IList<CreateCaseOutput>> CreateCase(
    CreateCaseInput createCaseInput, 
    SaveCaseSearchInput saveCaseSearchInput) 
{ 
    // Omitted for brevity... 

    var AcctLst = 
     await rep.ExecuteStoredProcedureAsync<CreateCaseOutput>(
      strSPQuery, 
      listParam) 
      .ToList(); 

    if (!string.IsNullOrEmpty(AcctLst.ElementAt(0).o_case_seq.ToString())) 
    { 
     await SaveCaseSearch(saveCaseSearchInput, 
         AcctLst.ElementAt(0).o_case_seq) 
      .ContinueWith(r => Console.WriteLine(r.Result)); 
    } 

    Console.WriteLine("After the async call"); 
    return AcctLst; 
} 

这提供了一种更好的解决方案!