C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: ASP.NETでタイマーを置く場所


(過去ログ 115 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■68134 / inTopicNo.1)  ASP.NETでタイマーを置く場所
  
□投稿者/ ほうらい (6回)-(2013/09/25(Wed) 12:33:15)

分類:[ASP.NET (VB)] 

ASP.NET(VB)2008でwebアプリケーションを作成しています。
Frameworkのバージョンは3.5です。

1時間毎にメールを送信する処理をバックグラウンドで実行する為、1時間タイマーを使って割り込みを発生させ、そのコールバック関数の中でメール送信をしようと考えました。
使用しているタイマーは軽装の「System.Threading.Timer」です。

画面は3つあり、トップ画面のaspx.vbファイルのLoadイベントの中で、

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
  Dim timerDelegate As TimerCallback = New TimerCallback(AddressOf MyClock)

  timer = New Timer(timerDelegate, Nothing, 0, 3600000)
End If
End Sub

Public Sub MyClock(ByVal o As Object)
SendMail()
End Sub

とコーディングしました。
しかし、トップ画面をずっと表示しているうちはタイマーのコールバック関数は1時間ごとに1回呼び出されるのですが、トップ画面から別の画面へ移動し再びトップ画面に戻るとトップ画面のLoadイベントが発生し、タイマーが新しく起動され、画面を移動するたびにコールバック関数が呼び出されます。

タイマーの生成処理をどこに書けばいいのか分かりません。
アプリケーションが起動時に1回だけ通るようなところはあるのでしょうか?

アドバイスを頂きたいです。
よろしくお願いいたします。

引用返信 編集キー/
■68137 / inTopicNo.2)  Re[1]: ASP.NETでタイマーを置く場所
□投稿者/ WebSurfer (59回)-(2013/09/25(Wed) 13:06:58)
No68134 (ほうらい さん) に返信
> ASP.NET(VB)2008でwebアプリケーションを作成しています。
> Frameworkのバージョンは3.5です。
>
> 1時間毎にメールを送信する処理をバックグラウンドで実行する為、1時間タイマーを使って割り込みを発生させ、そのコールバック関数の中でメール送信をしようと考えました。
> 使用しているタイマーは軽装の「System.Threading.Timer」です。
>
> 画面は3つあり、トップ画面のaspx.vbファイルのLoadイベントの中で、
>
> Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
> If Not IsPostBack Then
>   Dim timerDelegate As TimerCallback = New TimerCallback(AddressOf MyClock)
>
>   timer = New Timer(timerDelegate, Nothing, 0, 3600000)
> End If
> End Sub
>
> Public Sub MyClock(ByVal o As Object)
> SendMail()
> End Sub
>
> とコーディングしました。
> しかし、トップ画面をずっと表示しているうちはタイマーのコールバック関数は1時間ごとに1回呼び出されるのですが、トップ画面から別の画面へ移動し再びトップ画面に戻るとトップ画面のLoadイベントが発生し、タイマーが新しく起動され、画面を移動するたびにコールバック関数が呼び出されます。
>
> タイマーの生成処理をどこに書けばいいのか分かりません。
> アプリケーションが起動時に1回だけ通るようなところはあるのでしょうか?
>
> アドバイスを頂きたいです。
> よろしくお願いいたします。
>

以下のところ、間違いないですか? 

> 使用しているタイマーは軽装の「System.Threading.Timer」です。
> しかし、トップ画面をずっと表示しているうちはタイマーのコールバック関数は1時間ごとに1回呼び出されるのですが、

サーバー側で動く System.Threading.Timer を使っても意味はないはずです。

何故なら、サーバーは応答を返した後、応答を作るのに使ったアセンブリ等をメモリから全て削除しますので、タイマー
は動かないはずです。なので「タイマーのコールバック関数は1時間ごとに1回呼び出される」ことはないはずなのですが。
引用返信 編集キー/
■68138 / inTopicNo.3)  Re[2]: ASP.NETでタイマーを置く場所
□投稿者/ ほうらい (7回)-(2013/09/25(Wed) 13:26:23)
No68137 (WebSurfer さん) に返信
> 以下のところ、間違いないですか? 
>
>>使用しているタイマーは軽装の「System.Threading.Timer」です。
>>しかし、トップ画面をずっと表示しているうちはタイマーのコールバック関数は1時間ごとに1回呼び出されるのですが、
>
> サーバー側で動く System.Threading.Timer を使っても意味はないはずです。
>
> 何故なら、サーバーは応答を返した後、応答を作るのに使ったアセンブリ等をメモリから全て削除しますので、タイマー
> は動かないはずです。なので「タイマーのコールバック関数は1時間ごとに1回呼び出される」ことはないはずなのですが。

WebSurfer さん、レスポンスありがとうございます。

コールバック関数は呼び出されています。
ただ、テストをするのに1時間は待っていられないので
timer = New Timer(timerDelegate, Nothing, 0, 600000) '10分
'timer = New Timer(timerDelegate, Nothing, 0, 3600000)こっちは1時間
としています。
これで起動すると、10分ごとにコールバック関数が呼び出され、メールが送信されています。

引用返信 編集キー/
■68143 / inTopicNo.4)  Re[3]: ASP.NETでタイマーを置く場所
□投稿者/ WebSurfer (60回)-(2013/09/25(Wed) 16:20:06)
No68138 (ほうらい さん) に返信
> ■No68137 (WebSurfer さん) に返信
>>以下のところ、間違いないですか? 
>>
> >>使用しているタイマーは軽装の「System.Threading.Timer」です。
> >>しかし、トップ画面をずっと表示しているうちはタイマーのコールバック関数は1時間ごとに1回呼び出されるのですが、
>>
>>サーバー側で動く System.Threading.Timer を使っても意味はないはずです。
>>
>>何故なら、サーバーは応答を返した後、応答を作るのに使ったアセンブリ等をメモリから全て削除しますので、タイマー
>>は動かないはずです。なので「タイマーのコールバック関数は1時間ごとに1回呼び出される」ことはないはずなのですが。
>
> WebSurfer さん、レスポンスありがとうございます。
>
> コールバック関数は呼び出されています。
> ただ、テストをするのに1時間は待っていられないので
> timer = New Timer(timerDelegate, Nothing, 0, 600000) '10分
> 'timer = New Timer(timerDelegate, Nothing, 0, 3600000)こっちは1時間
> としています。
> これで起動すると、10分ごとにコールバック関数が呼び出され、メールが送信されています。
>

Web サーバーが、最初の要求を返した 10 分後にメールを送信すると言っ
ています?

その時点ではサーバー側に存在しないはずのタイマーがなぜ動くのか摩訶
不思議です。(正直言うと、ちょっと疑ってます)

何にせよ、Web サーバーはクライアント側からの呼び出しに応じて応答を返
すというのが基本で、メールを定期に送るというような作業を Web サーバー
側独自にやらせることに無理があります。

なので、Web アプリとは別に、定期的にメールを送信する Windows Service
などを作ることをお勧めします。

それがどうしてもダメで、Web サーバー側だけで何とか定期的にメールを送
りたいということであれば、タイマーを使うのではなく、以下のページにあ
るように Cache の期限切れのタイミングを利用して行うという方法もあるよ
うですので検討されてはいかがですか。

Simulate a Windows Service using ASP.NET to run scheduled jobs
http://www.codeproject.com/Articles/12117/Simulate-a-Windows-Service-using-ASP-NET-to-run-sc

引用返信 編集キー/
■68149 / inTopicNo.5)  Re[4]: ASP.NETでタイマーを置く場所
□投稿者/ ほうらい (8回)-(2013/09/26(Thu) 00:35:05)
2013/09/26(Thu) 00:38:05 編集(投稿者)
2013/09/26(Thu) 00:37:14 編集(投稿者)
2013/09/26(Thu) 00:36:56 編集(投稿者)

> Web サーバーが、最初の要求を返した 10 分後にメールを送信すると言っ
> ています?
>
> その時点ではサーバー側に存在しないはずのタイマーがなぜ動くのか摩訶
> 不思議です。(正直言うと、ちょっと疑ってます)

私が使用しているタイマーは一番最初に記載した通り、
System.Threading.Timer
です。
これはタイマーを作成したスレッドでは実行されず、システムが提供する ThreadPool スレッドで実行されるそうです。
今回、トップページのLoadイベントででタイマーを生成しているので、他のページにいって再びトップページに戻ってくると、
タイマーを生成するので、いくつもタイマーが起動し、しかしDISPOSEもしていないというか出来ず、
メモリーリークしていることが分かりました。
最悪だ、ということは分かったので他の方法を考えたいと思います。
レスポンス下さりありがとうございました。

※MSDNの解説です
TimerCallback デリゲートを使用して、Timer で実行するメソッドを指定します。タイマー デリゲートは、
タイマーの構築時に指定され、変更することはできません。
このメソッドは、タイマーを作成したスレッドでは実行されず、システムが提供する ThreadPool スレッドで実行されます。

解決済み
引用返信 編集キー/
■68151 / inTopicNo.6)  Re[5]: ASP.NETでタイマーを置く場所
□投稿者/ じゃんぬねっと (17回)-(2013/09/26(Thu) 02:25:01)
No68149 (ほうらい さん) に返信
> 2013/09/26(Thu) 00:38:05 編集(投稿者)
> 2013/09/26(Thu) 00:37:14 編集(投稿者)
> 2013/09/26(Thu) 00:36:56 編集(投稿者)
>
>>Web サーバーが、最初の要求を返した 10 分後にメールを送信すると言っ
>>ています?
>>
>>その時点ではサーバー側に存在しないはずのタイマーがなぜ動くのか摩訶
>>不思議です。(正直言うと、ちょっと疑ってます)
>
> 私が使用しているタイマーは一番最初に記載した通り、
> System.Threading.Timer
> です。
> これはタイマーを作成したスレッドでは実行されず、システムが提供する ThreadPool スレッドで実行されるそうです。
> 今回、トップページのLoadイベントででタイマーを生成しているので、他のページにいって再びトップページに戻ってくると、
> タイマーを生成するので、いくつもタイマーが起動し、しかしDISPOSEもしていないというか出来ず、
> メモリーリークしていることが分かりました。
> 最悪だ、ということは分かったので他の方法を考えたいと思います。

ちなみに、「最悪だ、」というのはどのあたりに対してでしょうか?
System.Threading.Timer クラスに対してですか? Dispose できない点ですか? いくつもタイマーが起動する点ですか?

いずれにしても、それはそういう scope (リクエスト スコープ) で実行するようにしているから、というのが発端です。
単純にそういう実装を知らず知らずにしてしまったことに対して「最悪だ、」なら良いのですが。

"他の方法" についてですが、老婆心ながら、Web アプリケーションでどうこうというのはやめた方が良いですよ。
上記の問題そのものは簡単に回避できますが、それが最適解でないことだけは明らかだからです。
他の方法というのが Web アプリケーション外のことであれば何も言うことはありません。
それは WebSurfer さんがすでに解説していることですので。

> レスポンス下さりありがとうございました。
>
> ※MSDNの解説です
> TimerCallback デリゲートを使用して、Timer で実行するメソッドを指定します。タイマー デリゲートは、
> タイマーの構築時に指定され、変更することはできません。
> このメソッドは、タイマーを作成したスレッドでは実行されず、システムが提供する ThreadPool スレッドで実行されます。

引用ありがとうございます。
正直言うと、Timer を使う機会なんてまったくない私には良い勉強になりました。
引用返信 編集キー/
■68152 / inTopicNo.7)  Re[6]: ASP.NETでタイマーを置く場所
□投稿者/ ほうらい (9回)-(2013/09/26(Thu) 02:39:33)
2013/09/26(Thu) 02:49:18 編集(投稿者)

No68151 (じゃんぬねっと さん) に返信
> ちなみに、「最悪だ、」というのはどのあたりに対してでしょうか?

もちろん無知な自分自身にですよ。
メモリーリークを発生させていたなんて恥ずかしい限りです。
もっと勉強します(反省)。

>
> "他の方法" についてですが、老婆心ながら、Web アプリケーションでどうこうというのはやめた方が良いですよ。
> 上記の問題そのものは簡単に回避できますが、それが最適解でないことだけは明らかだからです。

その通りだと思います。
アドバイスありがとうございました!

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -