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

質問:私ができるようにする必要があるのは、次に進む前に、そのリクエストがMakeRequest()から戻る必要がある時間を指定するIntervalInSecondsの値を各 Request に与えることです。たとえば、これを 10 に設定して 10 秒が経過した場合、先に進みたいと思い、既存の MakeRequest() 呼び出しを完全に忘れます。

これを達成するために使用できるさまざまな方法をたくさん調査しましたが、実際にそれを行う方法はわかりません。

4

2 に答える 2

1

明らかに、MakeRequest で行われている作業は IntervalInSeconds 秒よりも長く続く可能性があります。MakeRequest を同期的に実行する必要がある場合、経過時間を非常に定期的に確認できるループがない限り、メソッドを IntervalInSeconds 内に残すのは非常に困難です。良いアプローチではありません。

インターフェイス IRequest の変更を伴わない foreach ループの迅速かつ簡単なアプローチを次に示します。

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

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

もちろん、これには、この foreach ループが含まれるメソッドに Task (または void ですが、そうしないでください) 戻り値の型を指定する必要があります。

必要に応じて、MakeRequest がタイムアウト間隔自体を処理する、より複雑なソリューションを想像できます。

于 2013-03-08T19:30:18.790 に答える
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*/
}
于 2013-03-08T21:55:34.190 に答える