2015-03-03 46 views
0

我有兩種方法。我想等待第一個,有時候等待另一個(但不是所有的時間)。所以我想我應該使用一項任務,等待它,等待,而不是等待。將同步方法轉換爲與C#異步#

編輯:事實上,我只需要一個火,忘記呼叫? :

public class TestController : ApiController 
{ 
    public IHttpActionResult Get(int id) 
    { 
     Stopwatch sw = Stopwatch.StartNew(); 

     JobRunner runner = new JobRunner(); 
     bool iWantToWait = id == 1; 

     string jobId = runner.Run(!iWantToWait); 
     sw.Stop(); 
     return Ok("Ok " + jobId + " # " + sw.Elapsed); 
    } 
} 

public class JobRunner 
{ 
    public string Run(bool fireAndForget) 
    { 
     ShortMethodIAlwaysWantToWait(); 
     string jobId = Guid.NewGuid().ToString("N"); 
     if (fireAndForget) 
      HostingEnvironment.QueueBackgroundWorkItem(token => LongMethodICouldWantToWaitOrNot(jobId)); 
     else 
      LongMethodICouldWantToWaitOrNot(jobId); 
     return jobId; 
    } 

    private void ShortMethodIAlwaysWantToWait() 
    { 
     // ... 
    } 

    private void LongMethodICouldWantToWaitOrNot(string jobId) 
    { 
     // ... 
    } 
} 

回答

2
public class JobRunner 
{ 
    public async Task<string> Run(bool fireAndForget) 
    { 
     await ShortMethodIAlwaysWantToWait(); 
     string jobId = Guid.NewGuid().ToString("N"); 
     if (fireAndForget) 
      HostingEnvironment.QueueBackgroundWorkItem((token) => LongMethodICouldWantToWaitOrNot(jobId)); 
     else 
      await LongMethodICouldWantToWaitOrNot(jobId); 
     return jobId; 
    } 

    private async Task LongMethodICouldWantToWaitOrNot(string jobId) 
    { 
     await Task.Delay(5000); 
    } 

    private async Task ShortMethodIAlwaysWantToWait() 
    { 
     await Task.Delay(2000); 
    } 
} 

照顧後臺任務在ASPNET,淨4.5.2之前,你不應該「射後不理」異步方法,因爲線程可以的結束前被中止任務。由於4.5.2可以使用HostingEnvironment.QueueBackgroundWorkItem

+0

雖然請注意,由於LongMethod現在在同一個線程上運行,因此您不會等待'ShortMethodIAlwaysWantToWait' – 2015-03-03 10:11:38

+0

。雖然可以很容易地用'await Task.Run()'在另一個線程上運行。 – GazTheDestroyer 2015-03-03 10:11:43

+0

感謝您的回答。 Thread.Sleep當然是一個例子,我正在訪問一些資源。我是否需要異步LongMethodICouldWantToWaitOrNot?或者它只能是一個空白? – Tim 2015-03-03 10:13:07

0
 public async Task<string> Run() 
     { 
      ShortMethodIAlwaysWantToWait(); 
      string jobId = Guid.NewGuid().ToString("N"); 

      if (iwantToAWait) { 
       var task = Task.Run(() => LongMethodICouldWantToWaitOrNot(jobId)); 
       await task; 
      } 
      else 
       LongMethodICouldWantToWaitOrNot(jobId) 

      return jobId; 
     } 

這樣,Task要麼等待:在控制返回給調用者,那麼誰可以決定是否要等待或等待,或Task是等待而阻斷當前線程。

你可能想要麼改變你的動作要async和更新的呼叫:

string jobId = await runner.Run(); 

,也可以使用Task<string>

var task = runner.Run(); 
task.Wait(); 
string jobId = task.Result; 

編輯做同樣的:重要的是是否LongMethodICouldWantToWaitOrNot正在執行CPU綁定操作,在這種情況下,使用Task.Run運行它是有意義的,或者該方法的「緩慢」是否由I/O操作引起,在這種情況下,您應該使其成爲async,我看不到任何同步運行的原因

+0

'異步'方法中的'Wait'?什麼是在線程池線程中執行並同步等待?爲什麼不調用'LongMethodICouldWantToWaitOrNot'? – 2015-03-03 10:16:33

+0

這就是OP要求的。我不是挑戰問題的支持者。他想等待或等待,取決於某些內容......在線程池中執行確實是不必要的。更新答案。 – Steves 2015-03-03 10:20:58

+0

我有時會等待,有時候不會。我看不到OP要求什麼時候同步等待。真的問題至少對我來說還不清楚。但是,如果你想在'async'方法中同步等待,那麼你正在做一些非常錯誤的事情。 – 2015-03-03 10:25:40