2

私は過去 12 時間、このテーマについて熟考してきましたが、どうにもならないような気がします。これが可能かどうかさえわかりませんが、私のプロジェクトを継続するのに大いに役立つので、そうであることを願っています.

私がやろうとしているのは、コルーチンを作成して、使用する特定のプログラムが非同期 http 要求を実行できないためにフリーズしないようにすることです。コルーチンについての私の理解はまだ「え?それはどのように機能するのですか?」の中にありますが、その部分を行う方法を理解しました 段階。私の問題は、複数のリクエストに正しい情報で応答できるようになったことです。たとえば、次の場合、3 つの別個の応答が生成されます。

foo(a)
foo(b)
foo(c)

wherefooは内部のパラメーターを使用してコルーチンを開始します。すべてが個別に要求された場合、適切な結果が返されます。ただし、ブロックとして要求された場合は、foo(c)の結果のみが返されます。今、私はこの背後にある理由を理解していますが、ブロックとして要求されたときに 3 つの結果すべてを返すようにする方法を見つけることができません。この問題を少し理解するために、実際のコードを次に示します。

function background_weather()
local loc = url.escape(querystring)
weatherpage = http.request("http://api.wunderground.com/api/004678614f27ceae/conditions/q/" .. loc .. ".json")
wresults = json.decode(weatherpage)
--process some stuff here, mainly datamining
end
--send datamined information as a response
coroutine.yield()
end

そして、コルーチンの作成:

function getweather ()
-- see if backgrounder running
  if background_task == nil or
   coroutine.status (background_task) == "dead" then
-- not running, create it
   background_task = coroutine.create (background_weather)
-- make timer to keep it going
 AddTimer ("tickler", 0, 0, 1, "",
           timer_flag.Enabled + timer_flag.Replace,
           "tickle_it")
  end  -- if
end -- function

querystring変数は最初のリクエストで設定されます。ここには含めませんでしたが、テストのため12345に変数として使用しquerystringます。タイマーは、スクリプトの元の作成者がコルーチンがまだ実行されているかどうかを確認するために初期化し、完了するまで毎秒バックグラウンドを突き刺したものです。正直なところ、プログラム内で非同期に実行されているように見えますが、これが正しく行われたかどうかさえわかりません。

では、1 つのブロックで複数のリクエストを受け取り、複数のレスポンスを返すことは可能ですか? それとも、これは Lua が処理するには多すぎるタスクなのでしょうか?

4

2 に答える 2

5

コルーチンはそのようには機能しません。実際、それらはブロックしています。

コルーチンが解決する問題は、「しばらく実行できる関数が必要で、戻って別のことを行い、戻ってきて、終了したときと同じ状態になりたい」です。

「他のことをしている間も実行し続けたい」とは言っていないことに注意してください。コードの流れはコルーチンで「停止」し、コルーチンに戻ったときにのみ続行します。

コルーチンを使用すると、コードの動作を変更 (場合によっては容易に) して、コードをより明確に、または読みやすくすることができます。ただし、厳密にはシングルスレッドです。

Lua が実装するものは C99 で指定する必要があることに注意してください。この標準にはスレッド実装が付属していないため、Lua はデフォルトで厳密にシングルスレッドです。マルチスレッドが必要な場合は、外部ライブラリにフックする必要があります。たとえば、luvitはこれを実現するために libuv lib で Luajit をフックします。

いくつかの良い参考文献:

于 2012-07-15T11:48:58.220 に答える
1

Programming in Lua の9.4 章には、ビジーループを防ぐためにコルーチンと LuaSocket の socket.select() 関数を使用して、この正確な問題に対処する方法のかなり良い例が含まれています。

残念ながら、socket.select で socket.http 関数を使用する方法はないと思います。多くの場合、PiL の例のコードだけで十分ですが、要求された URL がリダイレクトを送信するなど、かなり一般的なケースは処理されません。

于 2012-07-15T20:34:08.920 に答える