0

我有一個有趣的場景,我遇到了問題,而且我無法確定最佳解決方案。定時方法調用 - 如何在沒有等待操作完成時間到期時繼續工作?

說我有以下的foreach循環

Request[] requestArray = //Get Array of Request objects from somewhere 

foreach(IRequest r in requestArray) 
{ 
     var response = r.MakeRequest(); 
} 

public class Request:IRequest 
{ 
     public double IntervalInSeconds {get;set;} //Allowed Time To Complete Request 

     public Response MakeRequest() 
     { 
      //Perform arbitrary operation, could be long or short running 
     } 
} 

public interface IRequest 
{ 
     Response MakeRequest(); 
} 

問:我需要能夠做的就是爲IntervalInSeconds是指定的要求有多長時間了給每個請求的值在我們繼續之前從MakeRequest()返回。例如,如果我們將其設置爲10,並且經過10秒,我想繼續前進,並且完全忘記現有的MakeRequest()調用。

我研究了很多不同的方法可能用來完成這一點,但不知道如何真正做到這一點。

回答

0

我用以下解決方案:

for(int i = 0; i < requestArray.Length;i++) 
{ 
    var request = requestArray[i]; 
    var task = Task.Factory.StartNew<Response>(makeRequest); 

    Task.WaitAny(new Task[]{task},request.IntervalInSeconds * 1000); 

    if(task.Status == TaskStatus.RanToCompletion) 
    { 
     /*Done*/ 
     return task.Result; 
    }  
    /*Keep Going*/ 
} 
+0

那很好,如果你不介意額外的阻塞。 – 2013-03-10 09:47:29

1

很明顯,在MakeRequest中完成的工作可能會持續比IntervalInSeconds秒長。如果MakeRequest必須同步運行,那麼很難將該方法保留在IntervalInSeconds中,除非在那裏有一個循環,這允許您非常正常地檢查流逝的時間。不是一個好方法。

這裏是爲您的foreach循環一個快速和簡單的方法,不涉及改變接口IRequest:

foreach(IRequest r in requestArray) 
{ 
    var responseTask = Task.Run(r.MakeRequest); 

    await Task.WhenAny(responseTask, Task.Delay(TimeSpan.FromSeconds(r.IntervalInSeconds)); 
} 

當然,這需要這個foreach循環中,可給予任務的方法(或無效,但不要這樣做)返回類型。

我可以想象更復雜的解決方案,如果您需要,MakeRequest會自行處理超時時間間隔。

相關問題