C# 异步调用 cmd.exe 执行bcp命令的问题~~~拜托拜托!!

秋灵殇天 2016-05-22 01:49:35
我写了一个程序,需要大范围导出导入数据到SQL Sever中,数据量大约是400w条,上网搜了好久,最后决定使用BCP 命令。。。bcp命令是这么写的:

BCP “SQL 语句" queryout 文件路径.txt -c -k -t"\t" -r"\n" -S "服务器名" -U"用户名" -P"密码"

在cmd上直接调用木有问题,生成的也是全部的;从程序中运行,当数据量小于5w时也木有问题,
但数据量达到百万时,问题出现了
生成的txt文件只能到8M程序就停了!!!实际应该生成400M多的呢!!!!!!
然后将我自己的程序关闭后,,,,,它自己又把文件给生成出来了,全部的!!!400M多的!!!!

我希望达到的效果是全部生成出来,把这个不知道是什么的bug改掉~找了好久,结果,

我用的是backgroundwoker后台调用的,然后再dowork中调用的代理,beginInvoke开始,endInvoke获取返回值,对这块不怎么太熟,想说有没有可能是内存大小限制的问题,上网搜没搜到相关的,只好请教大神们了!!

这是相关代码:
public void DoWork(object sender, DoWorkEventArgs e)
{
DialogResult dr = MessageBox.Show("是否开始导出数据?", "提示", MessageBoxButtons.OKCancel);
exportOutFunc eif = new exportOutFunc(this.exportOut);
IAsyncResult IRIn = eif.BeginInvoke(dr, null, eif);
bool result = eif.EndInvoke(IRIn);
}

private bool exportOut(DialogResult dr)
{
//第二种方法
string temp = exportData.BCPexportOut(exportData.getOutSQL(), data1_FileFolder, "txt");
return true;
}
private string BCPexportOut(string sql,string filepath,string filetype)
{
string path = String.Format(filepath + getDBTableName() + "." + fileType);//获取生成文件路径
string execute = "BCP \"" + sql + "\" queryout "+ path +" -c -k -t\"\\t\" -r\"\\n\" -S \""+ sever +"\" -U\""+userId+"\" -P\""+password+"\"";
string cmdInfo = cmdcon.Execute(execute);//在cmd中执行语句的函数,还是那一套,就不贴了

return cmdInfo;
}

麻烦啦~~
...全文
308 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhaomin_33 2016-05-22
  • 打赏
  • 举报
回复
楼主说的对!
秋灵殇天 2016-05-22
  • 打赏
  • 举报
回复
楼主刚刚解决了这个问题,是在执行cmd时的问题。 个人觉得问题应该出现在没有将缓冲区刷到基本流上, 应该用process的StandardInput.WriteLine()函数,不用/c结束命令,用命令+exit的形式, 还有关键的 process.StandardInput.AutoFlush = true;//在调用streamWriter的write()时,将缓冲区输入到基本流 给自己一个提醒吧,这错误不要再犯
秋灵殇天 2016-05-22
  • 打赏
  • 举报
回复
回复1楼,因为这只是我一个程序的片段,backgroundworker主要是想解决其他问题的,所以在dowork中写的调用,不过按理来说逻辑上应该没差吧?? 在执行cmd命令中是有等待cmd命令结束的,下面是代码: //执行dos语句 //dosCommand Dos命令语句 public string Execute(string dosCommand) { return Execute(dosCommand, 0); } /// <summary> /// 执行DOS命令,返回DOS命令的输出 /// </summary> /// <param name="dosCommand">dos命令</param> /// <param name="milliseconds">等待命令执行的时间(单位:毫秒), /// 如果设定为0,则无限等待</param> /// <returns>返回DOS命令的输出</returns> public static string Execute(string command, int seconds) { string output = ""; //输出字符串 if (command != null && !command.Equals("")) { Process process = new Process();//创建进程对象 ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.FileName = "cmd.exe";//设定需要执行的命令 startInfo.Arguments = "/C " + command;//“/C”表示执行完命令后马上退出 startInfo.UseShellExecute = false;//不使用系统外壳程序启动 startInfo.RedirectStandardInput = false;//不重定向输入 startInfo.RedirectStandardOutput = true; //重定向输出 startInfo.CreateNoWindow = true;//不创建窗口 process.StartInfo = startInfo; try { if (process.Start())//开始进程 { if (seconds == 0) { process.WaitForExit();//这里无限等待进程结束 } else { process.WaitForExit(seconds); //等待进程结束,等待时间为指定的毫秒 } output = process.StandardOutput.ReadToEnd();//读取进程的输出 } } catch { } finally { if (process != null) process.Close(); } } return output; } 程序中,设置的是无限等待。 然后关于怎么看的文件,我是直接从文件夹中看的文件属性,当我的程序运行时,文件大小保持在8M左右(一直),但当我的程序被关闭后,我再次查看了文件大小,文件变大了,,,然后直到全部导出后,文件大小不动了(这期间,我就是不断地刷新目录来着),,,,然后,如果说我没等待进程结束的话,当数据量只有几万的时候,应该也会报错吧??但是没有出现问题,而且,我还等待了,,,
引用 1 楼 sp1234 的回复:
你这里贴的程序设计,基本上都是多余的东西。没有表明只要的内容。 你搞了一个 bool result = eif.EndInvoke(IRIn); 代码在这里阻塞当前线程,是什么意义呢?在 exportOu 方法中调用 eif.EndInvoke(IRIn) 语句就可以了,而根本不需要阻塞。 由于是真正的异步回调编程,那么这里的 DoWork 也就可以删除掉了。直接放到你的主程序中去 MsgBox对话,然后直接 BeginInvoke 注册一个异步回调 exportOut 就行了。 由于 DoWork 没用、删掉,那么你的整个 backgroundwoker 也就没用了。 最后,你的这个不过是“先显示一个 MsgBox 对话框,然后启动 BCP 程序”的简单的两行代码的程序,如果它垮了,不代表着 BCP 就不往文件里写数据了。你就算是用写字板程序去打开数据文件,也不过是看到的是当前文件的一部分数据,因为后台还在“一股脑、一股脑”地追加文件数据。 实际上你这个程序代码 cmdcon.Execute(...) 只是启动 BCP 进程而已。你没有等待 BCP 进程结束。不要纠结一堆什么“线程”之类的无关的东西,应该看到该看的地方。
  • 打赏
  • 举报
回复
你这里贴的程序设计,基本上都是多余的东西。没有表明只要的内容。 你搞了一个 bool result = eif.EndInvoke(IRIn); 代码在这里阻塞当前线程,是什么意义呢?在 exportOu 方法中调用 eif.EndInvoke(IRIn) 语句就可以了,而根本不需要阻塞。 由于是真正的异步回调编程,那么这里的 DoWork 也就可以删除掉了。直接放到你的主程序中去 MsgBox对话,然后直接 BeginInvoke 注册一个异步回调 exportOut 就行了。 由于 DoWork 没用、删掉,那么你的整个 backgroundwoker 也就没用了。 最后,你的这个不过是“先显示一个 MsgBox 对话框,然后启动 BCP 程序”的简单的两行代码的程序,如果它垮了,不代表着 BCP 就不往文件里写数据了。你就算是用写字板程序去打开数据文件,也不过是看到的是当前文件的一部分数据,因为后台还在“一股脑、一股脑”地追加文件数据。 实际上你这个程序代码 cmdcon.Execute(...) 只是启动 BCP 进程而已。你没有等待 BCP 进程结束。不要纠结一堆什么“线程”之类的无关的东西,应该看到该看的地方。

111,129

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧