これが本当に必要な理由: (下の edit3 の下の問題の簡単な説明)
想像してみましょう、私は twitter 用のアプリケーションを作成しようとしています。今または後で追加するのと同じ数のアカウントがあります (たとえば 10)。したがって、すべてのアカウントにはオプションがあります。
- RSS からつぶやきます。
- 人に従う;
- つぶやきをリツイートします。
1 つのアカウントについて話すとき、このタスクはすべてバックグラウンドで動作し、他のタスクと同期する必要があります。いずれかのアカウントで twite とフォローが一度に進行する (要求が多すぎる) ことはありません。
つまり、アカウントごとに一度に 1 つのタスクを作成する必要があります。これは、この瞬間にアクティブなアカウントごとに 1 つのスレッドを編成する必要があるということですか? しかし、すべてのアカウントに次に何をすべきかを伝える (キューをいっぱいにする) スレッドとは何でしょうか? あるアカウントはツイートしたいだけで、別のアカウントは単にリツイートして人々をフォローしています:
- (スレッド 1) アカウント A: RSS/ファイルから 1 日中ツイートしたい。
- (スレッド 2) アカウント B: 30 秒ごとにリツイートし、15 分ごとにフォローしたい。
- (スレッド 3) : 「アカウント A」のキューをいっぱいにする必要があります (make twite、make twite、make twite);
- (スレッド 4) : 「アカウント B」のキューをいっぱいにする必要があります (retwite を作成、retwite を作成 (15 分間、30 秒ごと) ... 人をフォロー、retwite を作成 ...);
この場合、アカウントごとに 1 つのスレッドが機能し (キューにあるもの -> 彼がそうした)、別のスレッドがキューをいっぱいにするだけで、機能の手動タスクを追加できます(現在、すべてのアカウントで、この twite のリツイートを作成します)。またはこの人に従ってください)、- すべてのキューに新しいタスクを追加し、すべてのスレッドをできるだけ早く実行します。
だから、私の目標(ターゲット)は、すべてのアカウントが自分の仕事をするべきアプリケーションを作成することであり、次に何をすべきかを伝えるオプションがあります(タスクの優先度を変更します)。
お聞きしたいのですが、キューについて、アカウントごとに約 2 スレッドでよろしいですか (おそらく、スレッドがアカウントを使用してタスクをマーク (区切り文字) として使用するグローバル キューである必要があります)、アドバイスをいただけないでしょうか。私のタスクについて何か。
編集: そして、そこにある最大の問題は、私が20のアカウントを作ったとしても、5つのスレッド(制限)しか持たないということです.グローバル)、その他は仕事をするためのものです-しかし、彼らは1つのアカウントのために仕事をすることができました(1つのスレッドはtwiteを作り、他のスレッドはユーザーをフォローし始めます)、そしてそれは私を窮地に陥らせます-理解できません、私はすべてをどのように整理すればよいですか?このスレッド。
Edit2:もう 1 つの問題: 実行時間。取得したタスクを実行する必要があるすべてのスレッド時間をチェックインする必要があります (次の 1 時間のタスクを計画します) (現在 23:55、このタスクは 23:59 に実行されます。次は何ですか? スキップしますか? スリープしますか?)。
時間を確認せず、実行する準備ができているタスクだけを追加するキューに入れるべきである場合、1 つのアカウント 1 つのタスクの問題が再び発生します (15 秒の遅延を追加する twite を追加する、20 秒の遅延を追加する retwite を追加する、人々をフォローする 60 秒の遅延) => 1 分ごとにキューに 3 つのタスクがありますが、1 つずつ実行する必要があります (100 個のアカウントがありますが、作業スレッドは 5 つしかありません (それらは互いに同期する必要があります。他のスレッドを実行するアカウント タスクは何ですか?)) .
Edit3 (簡単 にしましょう): わかりました、Twitter のことは忘れましょう。コンソールに何かを書き込む Windows デスクトップ アプリケーションを作成します (「ボブからこんにちは」、「ボブからこんにちは」、「ボブからさようなら」とします)。
プログラムに多くの名前 (Bob、Jack、John、Dave、Scott) を追加して、この名前がどのようなフレーズを記述する必要があるかを確認できます。
- Bob は 15 秒ごとに「Hello from Bob」のみを書き込みます。
- ジャックは 1 分ごとに「ジャックからこんにちは」と 5 秒ごとに「ジャックからこんにちは」と書きます。
- John write 'hello', 'hi', 'bye' + 'John' から 5 秒, 10 秒, 15 秒;
- など(20名とする);
私は願っています、それは大丈夫ですか?
したがって、今、アプリケーションを起動すると、この 20 個の名前のすべてがコンソールにフレーズを書き込む必要がありますが、時間内にすべてのスレッド (10 個のワーカー スレッドに制限させてください) に対して、名前ごとに 1 つのタスクのみをタスクにする必要があります。 (1 つのスレッドが「Hello from Jack」を書き込んでいる場合、このタスクを 01:42:00 に実行する必要がある場合でも、他のスレッドは「bye from Jack」を書き込んではいけません。Jack の 1 つのタスクが完了したときにのみ、他のスレッドが開始されます) .
(+) さらに、この名前の誰かに追加して、最も近いタスクが完了したらすぐに好きなフレーズを書くオプションが必要です。
私はあなたの助けを見つけることを願っています。
Edit4:そう:
助けてくれてありがとう、今、私は何が必要で、アプリケーションを整理する方法を知っています。
最後に実現:
私は自分のコードを使用してタスクを実行しましたが、私にとっての解決策は最高のようです。
したがって、すべてのアカウントのキューを生成し、それらをアプリケーション タスクの 1 つのグローバル キューに入れると、それを TimerCallBack 関数に渡します。この関数は、実行する準備ができているタスクがキューにあるかどうかをチェックします (ただし、event_elements[0] のみをチェックします)。 ),- その場合は、isactive = true を設定し (個人キューの場合、前の終了前に次のイベントを実行しないようにします)、このキューを配置します。これは、反復後の最初のイベントごとに実行されます。
次に、コレクションとして Parallel.ForEach に渡します。
Parallel.ForEach(readyToExec, new ParallelOptions { MaxDegreeOfParallelism = 5 }, eq =>
{
lock (eq)
{
QueueElement exec_elem = eq.elements[0];
Console.WriteLine(exec_elem.timeToExecute + ": " + eq.account.Name + " " + exec_elem.EventType);
exec_elem.timeToExecute = DateTime.Now + exec_elem.timeDelay;
eq.timeLastExecute = DateTime.Now;
eq.elements.Sort();
eq.isactive = false;
}
});
ちなみに、実行するイベントを追加する前にチェックを追加しました:
foreach (var equeue in queue)
{
if (!equeue.isactive && equeue.elements[0].readyToExecute)
{
if (DateTime.Now > equeue.timeLastExecute + TimeSpan.FromSeconds(5))
{
equeue.isactive = true;
readyToExec.Add(equeue);
}
else
{
equeue.elements[0].timeToExecute = DateTime.Now + TimeSpan.FromSeconds(5);
}
}
}
1 つのアカウントのイベントを手動で遅延させて実行する (たとえば、00:00:00 に「Hello」と書き込んだ場合、次のイベントは 00:00:05 まで実行を開始できませんでした。この実行の時間が 00 であっても) :00:02)。
だから、それは私にとってとてもうまくいきます;)