如何创建由“开始”和“停止”按钮控制的CSV文件
本文关键字:停止 按钮 控制 文件 CSV 开始 何创建 创建 | 更新日期: 2023-09-27 18:00:25
我想设计一个windows窗体应用程序,将我的数据(约70k值)放在一个数组中,以便在最短的时间内将其传输到csv文件,csv文件路径和名称由windows窗体应用程序给定。
数据传输仅在第一个名为"开始"的按钮被按下时完成,而当第二个按钮"停止"被按下时,无论值的数量如何,数据传输都应该停止。
这是代码:
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());
}
这是我正在使用的函数,它有一个数组varibale dscaledData。我想从这个数组中获取值,并将其存储在csv文件中
Write(dScaledData, @csvadd);
@部分显示带有名称的csv路径存储在dscaledData变量中的数据值非常大,大约70k
您希望使用停止按钮以某种方式中断写入循环。但事实上,它将继续运行,并确实阻塞ui线程。因此,您需要在不同的线程中运行写循环。。
在.NET中有多种方法可以实现,例如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());
}
关于定时情况的一些注意事项:
向StringBuilder
添加70k行应该不会花费很多时间。看看我的代码:我必须将测试数据拖动到10M行,才能按下机器上的停止按钮!
也许数据的创建是瓶颈,也许是写入磁盘。。?或者可能没有瓶颈??在决定实现之前,您应该了解这一点!
如果其他部分被识别为瓶颈,您将不得不相应地更改代码以脱离其他循环。。
我添加了回调机制,这样您就可以看到如何将有关任务进度的信息带回UI线程。它应该帮助用户决定停止任务是否有意义。。
但是添加回调会大大降低速度,所以不必为每一行调用它,而是可以这样做:if (i % 1000 == 0 ) aCallback(i);
,并且每1000行只更新进度标签(当然也可以是ProgressBar
)。
您需要使用BackgroundWorker来完成此操作。这正是你所需要的。
不要使用File.WriteAllText,而是在工作线程中使用File.WitLine。
在我看来,70k行并不多,如果你的数据量在未来没有大幅增长,除非你用Thread.Sleep()
手动暂停编写器线程,否则人类将无法启动/停止