スケジュールされたタスクを実行する最良の方法[終了]


229

今日、ASP.NET Webサイトのスケジュールされたタスクを実行するためのコンソールアプリケーションを作成しました。しかし、このアプローチは少しエラーが発生しやすく、維持するのが難しいと思います。スケジュールされたタスクをどのように実行しますか(windows / IIS / ASP.NET環境)

更新:

タスクの例:

  • データベースのメールキューからメールを送信する
  • データベースから古いオブジェクトを削除する
  • Google AdWordsから統計を取得し、データベースにテーブルを入力します。

実行しているタスクの例は何ですか?
JeffO、2009

4
あなたがチェックする必要がありatrigger.comを
Kousha

Pleskをお持ちの場合は、VBSを作成してタスクスケジューラにアドバタイズできます。net24.co.nz/ kb
article

回答:


74

Webサイトのすべてのタスク(スケジュールが必要)はWebサイト内に保持され、特別なページから呼び出されます。次に、このページを時々呼び出す単純なWindowsサービスを作成しました。ページが実行されると、値が返されます。実行する作業がまだあることがわかっている場合は、すぐにもう一度ページを実行します。それ以外の場合は、しばらく実行します。これは私にとって非常にうまく機能しており、すべてのタスクロジックをWebコードで保持します。単純なWindowsサービスを作成する前に、Windowsスケジューラーを使用して、x分ごとにページを呼び出しました。

これを実行するもう1つの便利な方法は、Pingdomなどの監視サービスを使用することです。サービスコードを実行するページにhttpチェックをポイントします。ページが結果を返すようにします。この結果を使用して、何かが正しくない場合にPingdomをトリガーしてアラートメッセージを送信できます。


3
これが私が最終的に解決したソリューションです。カスタムWebサービスの代わりに、Windowsスケジューラー+カールを使用します。Windowsサービスを使用する利点は何ですか。
Niels Bosma

16
キャッシュアイテムの有効期限テクニックを確認しましたか?:私はあなたはそれがスケジュールされたサービスのはるかに理想的な実装であることがわかりになると思いcodeproject.com/KB/aspnet/ASPNETService.aspx
リチャード・クレイトン

10
悪意のあるユーザー(または検索エンジンのスパイダー)がこのページを呼び出して、スケジュールされたタスクが実行されるのを防ぐにはどうすればよいですか?
UpTheCreek 2009年

8
静的なタイムスタンプをWebアプリに保存し、タイムスタンプが設定されていない(最初の呼び出し)か、最後の呼び出しから正しい時間が経過した場合にのみ実行することで、悪意のある呼び出しを停止できます。
Rob Kent

5
IPアドレスが内部アドレスであるかどうかを確認することで、URLへの悪意のある呼び出しを阻止します。それが私たちの組織の内部にない場合、何も返さず、何もしません。
user1408767 2016

128

StackoverflowのためのJeff Atwoodによるこの手法は、私が遭遇した最も簡単な方法です。ASP.NETのキャッシュシステムに組み込まれた「キャッシュアイテムが削除されました」コールバックメカニズムに依存しています

更新:Stackoverflowはこのメソッドを超えています。これはWebサイトの実行中にのみ機能しますが、多くの人にとって役立つ非常にシンプルな手法です。

Quartz.NETもチェックしてください


12
では、アプリケーションが実行されていなくても、スケジュールされたタスクを実行する必要がある場合はどうなりますか?
MichaelGG

2
このため、タスクの実行に時間がかかる場合、ユーザーエクスペリエンスが低下する可能性もあります。ユーザーにメンテナンス/タスクをスポーンさせないようにします。
Brettski、2009

5
これは地獄のように怖いです!何かが原因でアプリケーションの実行が停止する可能性があり、おそらく次のユーザー要求でのみ再起動します。その間、タスクは実行されません。
teedyay 2009

43
元のブログ投稿へのコメントで今日気付いたこと: No, we’ve switched to a dedicated task. We definitely outgrew this technique. I do think it’s fine for small sites though!
-Jeff

3
-1このアプローチには大きな欠陥があります。アプリケーションがリサイクルされるたびに、「CacheItemRemoved」イベントが発生し、スケジュールされたタスクが実行されます。本番サイトでは、これは1日に数回発生する可能性があります。タスクを毎週実行する場合は、あまり良くありません。
Steven de Salas 2014年

30

カスタムWindowsサービスを作成します。

私はいくつかのミッションクリティカルなタスクをスケジュールされたコンソールアプリとしてセットアップしていて、それらを維持するのが難しいと感じました。私は、DBのスケジュールを数分ごとにチェックする「ハートビート」を備えたWindowsサービスを作成しました。本当にうまくいきました。

そうは言っても、重要ではないメンテナンスタスクのほとんどには、引き続きスケジュールされたコンソールアプリを使用しています。壊れていない場合は修正しないでください。


7
ちなみにリンクは今死んでいます。
Charles Burns

1
@CharlesBurnsは、あなたは常にarchive.orgで死んだリンクを閲覧することができます:web.archive.org/web/20090919131944/http://www.dotheweb.net/...
ニコレイ・コストーブ

17

これは関係者全員にとって簡単であることがわかりました。

  • DoSuchAndSuchProcessなどのWebサービスメソッドを作成する
  • このWebメソッドを呼び出すコンソールアプリを作成します。
  • タスクスケジューラでコンソールアプリをスケジュールします。

この方法論を使用すると、すべてのビジネスロジックがWebアプリに含まれますが、Windowsタスクマネージャーやその他の商用タスクマネージャーの信頼性があり、開始して実行レポートなどの戻り情報を記録できます。ページに投稿する代わりにWebサービスを使用すると、Webサービスから戻りデータを取得しやすくなるため、少し有利です。


10

ホイールを再発明する理由は、ThreadingクラスとTimerクラスを使用することです。

    protected void Application_Start()
    {
        Thread thread = new Thread(new ThreadStart(ThreadFunc));
        thread.IsBackground = true;
        thread.Name = "ThreadFunc";
        thread.Start();
    }

    protected void ThreadFunc()
    {
        System.Timers.Timer t = new System.Timers.Timer();
        t.Elapsed += new System.Timers.ElapsedEventHandler(TimerWorker);
        t.Interval = 10000;
        t.Enabled = true;
        t.AutoReset = true;
        t.Start();
    }

    protected void TimerWorker(object sender, System.Timers.ElapsedEventArgs e)
    {
        //work args
    }

7
タイマーを開始するためにスレッドを生成する必要はありません...
Zyo

4
私もそれが理想的な解決策だとは思わない。
Idan Shechter 2012

12
@IdanShechterこれが理想的なソリューションではないと考える理由を教えてください
Omu

2
スレッドはHttpRequestではないため、問題が発生する可能性があります。HttpRequestに関連する一部のデータはnullになる可能性があります。たとえば、HttpRequest .ApplicationPathの場合。タスクが適切に記述されていれば、機能します。別の問題は、アプリケーションプールの再起動です。プールが頻繁に再起動している場合(メモリリーク...)、ワーカーは実行されません。
Tomas Kubes 2013年

2
複数のインスタンスが実行されている場合(例:負荷分散)-おそらくこのソリューションは必要ないでしょう(複数のタスクが同じことを実行します)
Illidan

8

Windowsスケジューラを使用してWebページを実行します。

悪意のあるユーザーまたは検索エンジンのスパイダーによる実行を防ぐには、スケジュールされたタスクを設定するときに、クエリ文字列を使用してWebページを呼び出します。つまり、mypage.aspx?from = scheduledtask

次に、ページの読み込みで、条件を使用します:if(Request.Querystring ["from"] == "scheduledtask"){// executetask}

このようにして、検索エンジンのスパイダーや悪意のあるユーザーは、スケジュールされたタスクを実行できなくなります。


5
さらに良いのは、魔法のフレーズよりも少しセキュリティが高いクエリ文字列を実際に検証するソルトハッシュアルゴリズムを使用することです。要求は、mypage.aspx?salt = foo&hash = 1223523jbhdgu13t1のようなものになります。サーバーとクライアントの両方で同じハッシュアルゴリズムを使用する必要があります。また、サーバーにハード制限を追加します。実行時に保存し、実行が速すぎないようにします。でも私は偏執狂かもしれません。
Nenotlep 2013

14
さらに安全にするには、Windowsスケジューラを使用して、リクエストがサーバー自体からのものかどうかをチェックするWebページを実行します。Request.IsLocal>>サーバー自体だけがスケジュールされたタスクを実行でき、他のユーザーは実行できません。
陰謀

あなたのアプローチからより多くの経験がありますか?私はアプリの同様のタイプのサービスを開発するつもりでしたが、スケジュールされたタスクまたはcronでページを呼び出す方がよいのか、キャッシュシステムを使用するのかを判断できません。
JayDee


3

さらに、アプリケーションでSQL SERVERを使用している場合は、SQLエージェントを使用してタスクをスケジュールできます。これは、データ駆動型の繰り返し発生するコード(メールのリマインダー、定期メンテナンス、パージなど)を一般的に配置する場所です。SQLエージェントに組み込まれている優れた機能は、重要なタスクが失敗した場合に警告できる失敗通知オプションです。


2

予定されているタスクの種類がわかりません。「毎時間、foo.xmlを更新する」タイプのタスクなどを意味する場合は、Windowsスケジュールタスクシステムを使用してください。(「at」コマンド、またはコントローラー経由。)コンソールアプリを実行するか、プロセスを開始する特別なページを要求します。

編集:追加する必要があります。これは、スケジュールされたポイントでIISアプリを実行するためのOK方法でもあります。したがって、DBを30分ごとにチェックし、一部のデータについてユーザーにリマインダーを電子メールで送信する場合、スケジュールされたタスクを使用してこのページを要求し、IISで処理を行うことができます。

ニーズがより複雑な場合は、Windowsサービスを作成し、ループを実行して必要な処理を実行することを検討してください。これには、スケーリングまたは管理の目的でコードを分離するという利点もあります。欠点としては、Windowsサービスに対処する必要があります。


2

サーバーを所有している場合は、Windowsタスクスケジューラを使用する必要があります。AT /?を使用します コマンドラインからオプションを表示します。

それ以外の場合は、Webベースの環境から、別のマシンをセットアップして一定の間隔で特定のページにリクエストを送信するなど、厄介なことを行う必要があります。


2

ASP.NETプロジェクトでAbidarを正常に使用しました(ここにいくつかの背景情報があります)。

このメソッドの唯一の問題は、ASP.NET Webアプリケーションがメモリからアンロードされると(つまり、使用率が低いため)、タスクが実行されないことです。私が試したことの1つは、Webアプリケーションを5分ごとにヒットしてそれを維持するタスクを作成することですが、これは確実に機能するようには見えなかったため、代わりにWindowsスケジューラと基本的なコンソールアプリケーションを使用しています。

理想的な解決策は、Windowsサービスを作成することですが、これは不可能かもしれません(つまり、共有ホスティング環境を使用している場合)。また、メンテナンスの観点からは、Webアプリケーション内に物事を維持することが少し簡単になります。


1

ここに別の方法があります:

1)タスクの起動が期限切れまたは期限切れの場合にタスクを起動する「ハートビート」Webスクリプトを作成します。

2)Webscriptにアクセスして定期的に実行するように強制するスケジュールされたプロセスをどこかに(できれば同じWebサーバー上に)作成します。(WindowsはIEまたはwhathaveyouを使用してHeatbeatスクリプトを静かに起動するタスクをスケジュールします)

タスクコードがWebスクリプト内に含まれているという事実は、Webアプリケーションのコードベースにコードを保持するためだけのものです(両方が相互に依存していることが前提です)。これは、Web開発者が管理しやすくなります。 。

代替のアプローチは、すべてのスケジュール作業自体を実行し、実行可能ファイル自体をスケジュールされたタスクとして実行する実行可能サーバースクリプト/プログラムを作成することです。これにより、Webアプリケーションとスケジュールされたタスク間の基本的な分離が可能になります。したがって、Webアプリケーション/データベースがダウンしているかアクセスできない場合でも、スケジュールされたタスクを実行する必要がある場合は、このアプローチを使用する必要があります。


1
@マティアス、代わりにスケジュールされたプロセスに実際の仕事をさせてみませんか?
LukeH、2009

1

'ThreadPool.RegisterWaitForSingleObject'メソッドを使用すると、一定の間隔でコードを実行するWindowsサービスを簡単に作成できます。それは本当に洗練されていて、セットアップするのは非常に簡単です。この方法は、フレームワークでタイマーを使用するよりも効率的な方法です。

詳細については、以下のリンクをご覧ください。

Windowsサービスを使用して.NETで定期的なプロセスを実行する:http :
//allen-conway-dotnet.blogspot.com/2009/12/running-periodic-process-in-net-using.html


0

コンソールアプリケーションも使用します。Log4netのようなロギングツールを使用すると、その実行を適切に監視できます。また、適切に設計されていれば、同じコードライブラリの一部を2つの間で共有している可能性があることを考えると、それらがWebページよりも維持が難しいかどうかはわかりません。

これらのタスクを時間ベースで実行させたくない場合は、Webページの管理セクションにキューとして機能するWebページを置くことができます。ユーザーがタスクを実行するリクエストを入力すると、MyProcessQueueテーブルに空の日付スタンプレコードが挿入され、スケジュールされたタスクがMyProcessQueueの新しいレコードをX分ごとにチェックしています。このようにして、顧客が実行したい場合にのみ実行されます。

これらの提案がお役に立てば幸いです。


0

1つのオプションは、Windowsサービスをセットアップして、スケジュールされたタスクを呼び出すようにすることです。

タイマーを使用したwinformsでこれをASP.NETでうまく機能するとは思わない


-1

.NET用の新しいタスクスケジューラクラスライブラリ

注:このライブラリが作成されてから、MicrosoftはWindows Vista用の新しいタスクスケジューラ(タスクスケジューラ2.0)を導入しました。このライブラリは、タスクスケジューラ1.0インターフェイスのラッパーであり、Vistaでも引き続き使用でき、Windows XP、Windows Server 2003、およびWindows 2000と互換性があります。

http://www.codeproject.com/KB/cs/tsnewlib.aspx


削除してください。以下で回答しました。複製
Fandango68 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.