1

アプリにリクエストスロットリングを実装しました。これは、MemoryCacheを使用し、制限に従ってアイテムを期限切れにすることに基づいています。基本的に、私はキャッシュアイテムを取得しようとします。キャッシュアイテムがない場合は、先に進んでリクエストを行います。キャッシュアイテムの場合は、最後のリクエストを確認し、次にリクエストできる時間にワークアウトします。私の問題は、リクエストを待つ必要があるときにあります。

//This is a shortened version of what im doing, but the includes the required code

public void ThrottleRequest(string webservice)
{
    if (cache.TryGet(webservice))
    {
          var timeToWait = GetTimeToWaitFromSomewhere(); 
          Wait(timeToWait);
    }
}

public async void Wait(TimeSpan timeToWait)
{
     await Task.Delay(timeToWait); //This doesnt work
     Thread.Sleep(timeToWait); //This works
}

問題はwaitメソッドにあります。thread.sleep番号を使用すると、番号が一致し、リクエストが正しく調整されます(つまり、1秒あたり1リクエスト)が、本番環境ではこれを使用したくありません。では、ここで非同期的に待つ正しい方法は何ですか?APIなどを誤用していますか?

4

1 に答える 1

5

問題は、Waitメソッドのreturnタイプがvoid-基本的に「待機を開始し、待機を無視して続行します」と言っていることです。

あなたは通常それを次のように持っているでしょう:

public async Task ThrottleRequest(string webservice)
{
    if (cache.TryGet(webservice))
    {
        var timeToWait = GetTimeToWaitFromSomewhere(); 
        await Wait(timeToWait);
    }
}

public async Task Wait(TimeSpan timeToWait)
{
     await Task.Delay(timeToWait);
}

その時点では、あなたのWait方法は無意味であり、あなたは次のように書くほうがよいでしょう:

public async Task ThrottleRequest(string webservice)
{
    if (cache.TryGet(webservice))
    {
        var timeToWait = GetTimeToWaitFromSomewhere(); 
        await Task.Delay(timeToWait);
    }
}

メソッドを非同期に変更し、同様ThrottleRequestに返すように変更したことに注意してください。Task呼び出しがそれ自体で何を達成することを望んでいたかは明確ではありませんがWait、非同期を導入しようとしている場合は、何をしているのかを非常に明確にする必要があります。通常、非同期メソッドを呼び出すメソッド次のようになります。非同期。

現在実行中のスレッドを本当に一時停止したいだけの場合は、非同期メソッドをまったく使用しないでください。同期的ThrottleRequestに遅延させたいのですが、これはまさにその通りです。Thread.Sleep

現時点では、同期または非同期の観点から、コードが何をするのかを完全に明確に理解していないのではないかと強く思います。コード自体から一歩後退して、実際にどのように機能するかを考え(たとえば、スレッドモデルをどのようにするかを考えてください)、キーボード戻ります。

また、遅延が発生した後は、キャッシュを再度チェックしないことも考慮してください。つまり、20の異なるスレッドがそれぞれ一度にメソッドに入ると、そのうちの1つだけではなく、すべてがWebサービスにアクセスすることになります。そのため、残りはキャッシュされた結果を使用します。

于 2013-03-25T19:48:34.857 に答える