私たちのアプリケーションにメモリリークがあるかどうかをテストし、リクエストを処理している間にメモリ使用量が増加しすぎているかどうかを監視する必要があります。 私はapi/webserviceメソッドへの複数の同時呼び出しを行うためにいくつかのコードを開発しようとしています。このapiメソッドは非同期ではなく、操作を完了するまでに時間がかかります。c#webserviceをロードする方法
私はTasks、Threads、およびParallelismについて多くの研究を行ってきましたが、これまでは運がありませんでした。問題は、以下のすべてのソリューションを試した後でも、結果は常に同じです。その時点で2つの要求しか処理されていないようです。
が試み:
- >ループのためのシンプルな内部タスクを作成し、としてTaskCreationOptions.LongRunning
でそれらを設定せずに、それらを開始 - >ループのためのシンプルな内部スレッドを作成し、でとすることなく、それらを開始します優先度の高い
- >ループのためのシンプルでアクションのリストを作成し、使用してそれらを開始
Parallel.Foreach(list, options, item => item.Invoke)
- > Parallel.Forループ内で直接実行(以下)
- > MaxParallelism最大スレッド
に対して異なる値でみた - - >オプションとTaskScheduler
とないTPL方法を実行>this postもチェックしましたが、どちらも助けになりませんでした。
- > Stackoverflowの他の記事をチェックしましたが、F#ソリューションを使ってC#に正しく変換する方法がわかりません。 (私は...のF#を使用することはありません)
(msdnから取られたタスクスケジューラクラス)
ここで私が持っている基本的な構造です:
public class Test
{
Data _data;
String _url;
public Test(Data data, string url)
{
_data = data;
_url = url;
}
public ReturnData Execute()
{
ReturnData returnData;
using(var ws = new WebService())
{
ws.Url = _url;
ws.Timeout = 600000;
var wsReturn = ws.LongRunningMethod(data);
// Basically convert wsReturn to my method return, with some logic if/else etc
}
return returnData;
}
}
sealed class ThreadTaskScheduler : TaskScheduler, IDisposable
{
// The runtime decides how many tasks to create for the given set of iterations, loop options, and scheduler's max concurrency level.
// Tasks will be queued in this collection
private BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
// Maintain an array of threads. (Feel free to bump up _n.)
private readonly int _n = 100;
private Thread[] _threads;
public TwoThreadTaskScheduler()
{
_threads = new Thread[_n];
// Create unstarted threads based on the same inline delegate
for (int i = 0; i < _n; i++)
{
_threads[i] = new Thread(() =>
{
// The following loop blocks until items become available in the blocking collection.
// Then one thread is unblocked to consume that item.
foreach (var task in _tasks.GetConsumingEnumerable())
{
TryExecuteTask(task);
}
});
// Start each thread
_threads[i].IsBackground = true;
_threads[i].Start();
}
}
// This method is invoked by the runtime to schedule a task
protected override void QueueTask(Task task)
{
_tasks.Add(task);
}
// The runtime will probe if a task can be executed in the current thread.
// By returning false, we direct all tasks to be queued up.
protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return false;
}
public override int MaximumConcurrencyLevel { get { return _n; } }
protected override IEnumerable<Task> GetScheduledTasks()
{
return _tasks.ToArray();
}
// Dispose is not thread-safe with other members.
// It may only be used when no more tasks will be queued
// to the scheduler. This implementation will block
// until all previously queued tasks have completed.
public void Dispose()
{
if (_threads != null)
{
_tasks.CompleteAdding();
for (int i = 0; i < _n; i++)
{
_threads[i].Join();
_threads[i] = null;
}
_threads = null;
_tasks.Dispose();
_tasks = null;
}
}
}
とテストコード自体:
private void button2_Click(object sender, EventArgs e)
{
var maximum = 100;
var options = new ParallelOptions
{
MaxDegreeOfParallelism = 100,
TaskScheduler = new ThreadTaskScheduler()
};
// To prevent UI blocking
Task.Factory.StartNew(() =>
{
Parallel.For(0, maximum, options, i =>
{
var data = new Data();
// Fill data
var test = new Test(data, _url); //_url is pre-defined
var ret = test.Execute();
// Check return and display on screen
var now = DateTime.Now.ToString("HH:mm:ss");
var newText = $"{Environment.NewLine}[{now}] - {ret.ReturnId}) {ret.ReturnDescription}";
AppendTextBox(newText, ref resultTextBox);
}
}
public void AppendTextBox(string value, ref TextBox textBox)
{
if (InvokeRequired)
{
this.Invoke(new ActionRef<string, TextBox>(AppendTextBox), value, textBox);
return;
}
textBox.Text += value;
}
は、
私が得た結果は、基本的にはこれです。
[10:08:56] - (0) OK
[10:08:56] - (0) OK
[10:09:23] - (0) OK
[10:09:23] - (0) OK
[10:09:49] - (0) OK
[10:09:50] - (0) OK
[10:10:15] - (0) OK
[10:10:16] - (0) OK
etc
私が知る限り、サーバー側に制限はありません。私はParallel/Multitaskingの世界では比較的新しいです。これを行う他の方法はありますか?何か不足していますか?
(私はすべてのコードを簡略化するために単純化しましたが、提供されたコードは上記のシナリオを描写するのに十分であると考えています。何らかの関連性があるコードがあれば教えてください。編集して投稿することもできます)
ありがとうございます!
EDIT1:サーバーのログで2つずつリクエストが受信されていることを確認しました。実際に送信することに関連しています。 フレームワークが要求/接続をどのように管理するかは、ネットワークの問題または制限事項ですか?またはネットワークで何か(ネットとは無関係)?
EDIT2:忘れて、それはSOAP Webサービスです。
EDIT3:送信するプロパティ(データ内)の1つは、リクエストごとに変更する必要があります。
EDIT4:リクエストの各ペアの間には、関連する場合は常に〜25秒の間隔があることに気付きました。
[Webテスト](https://msdn.microsoft.com/en-us/library/ms182536(v= versus90).aspx)を使用してみましたか?特定のリクエストを記録し、[VS負荷テスト](https://www.visualstudio.com/en-us/docs/test/performance-testing/getting-started/getting-started-パフォーマンステストあり)。 – G0dsquad
ありがとう、私はそれを試していない、それを見てみましょう。しかし、私はWebメソッドだけをテストする必要があります。UIはありません。 Webテストを使用してそれを達成することは可能ですか?同時に、それを同時に実行することは可能ですか?なぜなら私はサーバーに同時にアクセスする要求が必要なのです。 –
もちろん、WebMethodにHTTPエンドポイントがある場合は、Webテストでリクエスト(データPOSTなど)を記録できます。次に、50人の並列ユーザーに対して、現実的な思考時間で10分間、負荷テストを設定することができます。 – G0dsquad