データ(約70kの値)を配列に入れて、最小限の時間でcsvファイルに転送するWindowsフォームアプリケーションを設計したいと思います。csvファイルのパスと名前は、Windowsフォームアプリケーションによって指定されます。
データ転送は、startという名前の最初のボタンが押されたときにのみ実行され、値の数に関係なく、2番目のボタンstopが押されたときに停止する必要があります。
コードは次のとおりです。
public static void Write(double[] data, string outputPath)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.GetLength(0); i++)
{
sb.AppendLine(string.Join(",", data[i]));
}
File.WriteAllText(outputPath, sb.ToString());
}
これは私が使用している関数で、配列であるvaribaledscaledDataを持っています。この配列から値を取得してcsvファイルに保存したい
Write(dScaledData, @csvadd);
@の部分は、名前の付いたcsvパスを示しています。dscaledData変数に格納されているデータ値は非常に大きいです。70k
停止ボタンを使用して、書き込みループをなんらかの方法で中断したいとします。しかし、それがそうであるように、それは実行を続け、実際にuiスレッドをブロックします。したがって、別のスレッドで書き込みループを実行する必要があります。
.NET、例えばAでそれを行うための様々な方法がありTask.Factory
、threads
またはBackgroundWorker
。
これは、Task.Factory
:を使用した単純ですが効果的な実装です。
stopped
から設定およびリセットするクラスレベル変数を作成しますButtons
。そこキャンセルする他、より複雑な方法ですTask
、ここを参照してくださいが、これは目的のために十分良い..です
私のテストでは、ダミーデータも作成します。
private void cb_Stop_Click(object sender, EventArgs e)
{ stopped = true; // this will be checked in our output loop }
private void cb_Start_Click(object sender, EventArgs e)
{
stopped = false;
// create my test data..
List<double> data = new List<double>();
for (int i = 0; i < 10000000; i++) data.Add((i+ 1d) / i * 1d );
string filename = "D:\\xxxxx.txt";
// this is an optional callback to provide feedback.
// It obviuosly slows things down greatly..
Action<int> callback = (value) => st_lines.Invoke(new Action(()
=> st_lines.Text = value + " lines written.."));
// now we start the write loop in another task..
// ..passing in our data and (optinally) the callback
Task myFirstTask = Task.Factory.StartNew(()
=> Write(data.ToArray(), filename, callback));
}
static bool stopped = true; // our flag
public static void Write(double[] data, string outputPath, Action<int> aCallback)
{ // your write loop
StringBuilder sb = new StringBuilder();
for (int i = 0; i < data.GetLength(0); i++)
{
if (stopped) break; // our new test
sb.AppendLine(string.Join(",", data[i]));
aCallback( i ); // optional callback
}
File.WriteAllText(outputPath, sb.ToString());
}
タイミング状況に関するいくつかの注意事項:
70k行をに追加するのにそれほどStringBuilder
時間はかからないはずです。私のコードを見てください。マシンの停止ボタンを押すことさえできるようにするには、テストデータを最大1,000万行までクランクする必要がありました。
データの作成がボトルネックであるか、ディスクへの書き込みである可能性があります。または多分ボトルネックはありませんか?実装を決定する前に、これを理解する必要があります。
他の部分がボトルネックとして識別された場合、他のループから抜け出すためにそれに応じてコードを変更する必要があります。
タスクの進行状況に関する情報をUIスレッドに戻す方法を確認できるように、コールバックメカニズムを追加しました。これは、タスクを停止することが理にかなっているかどうかをユーザーが判断するのに役立ちます。
ただし、コールバックを追加すると処理速度が大幅に低下するため、1行ごとに呼び出す代わりに、次のように行うことができます。if (i % 1000 == 0 ) aCallback(i);
進行状況ラベル(またはProgressBar
もちろん)を1000行ごとに更新するだけです。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加