0

JSON API に依存する Windows ストア アプリを作成しています。API のプロバイダーは、1 秒あたり 1 つを超える API リクエストが行われないように求めています。

そこで、ブロッキング キューにリクエストをキューイングできるクラスを作成し、バックグラウンド スレッドで次のようなループを実行します。

Loop
{
// this will block until a request is added to the queue
MyRequest = Queue.Take()

// Create task to make the api request here. 

Thread.Sleep(1000)
}

このようにして、別のリクエストをデキューしようとする前に、少なくとも 1 秒待機します。

Windows ストア アプリでは Thread.Sleep を使用できないことがわかりました。Task.Delay() は、呼び出されるたびに新しいタスクを作成するため、不必要に無駄に思えます。

私が気付いていない、これを行うための既知の方法がおそらくあると思いますか?

ありがとう、

4

2 に答える 2

3

Task.Delay() が無駄に思えることはわかっていますが、Microsoft の従業員とMSDN のモデレーターによって推奨されています。

.Sleep() または TGH が提案するような無限ループを使用すると、待機中にプログラムが応答しなくなります。キューの処理中に応答性を高めたい場合は、次のようなものを使用します。

await Task.Delay(1000);

于 2013-05-31T03:19:24.580 に答える
0

タスクをバックグラウンドで実行したい場合は、System.Threading.Timerをお勧めします。定期的なタイマーではなくワンショットとして設定し、リクエストごとに更新します。何かのようなもの:

System.Threading.Timer myTimer;

// initialize timer
myTimer = new Timer(TimerProc, null, 1000, Timeout.Infinite);

void TimerProc(object state)
{
    // do request here
    // then reset the timer
    myTimer.Change(1000, Timeout.Infinite);
}

これにより、1 つの要求が終了してから次の要求が開始されるまでに 1 秒待機する効果があります。

ティックを 1 秒間隔で実行する場合は、ティックがオーバーラップしないようにする必要があります。それは Monitor を使えば簡単です。ロック オブジェクトが必要で、タイマーを定期的なタイマーにするには:

object timerLock = new object();

// initialize periodic timer
myTimer = new Timer(TimerProc, null, 1000, 1000);

そしてあなたのタイマーproc:

void TimerProc(object state)
{
    if (!Monitor.TryEnter(timerLock))
    {
        // a request is currently being processed
        return;
    }
    try
    {
        // do request here
    }
    catch (expected exceptions)
    {
    }
    Monitor.Exit(timerLock);
}

ではないことに注意してMonitor.Exitくださいfinally。その理由については、Eric Lippert のLocks and exceptions do not mixを参照してください。

于 2013-05-31T04:47:11.870 に答える