2016-04-13 122 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; 
} 

這提供了一種更好的解決方案!