如果我有一个返回字符串的方法如下:
public string ExecuteCommandSync(object command)
{
string result = "";
try
{
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
result = proc.StandardOutput.ReadToEnd();
Console.WriteLine(result);
}
catch (Exception objException)
{
MessageBox.Show("error : " + objException.Message);
}
return result;
}
现在这适用于小数据,但如果我有大数据,它会挂起..
如果我把它放在线程中会使大数据更快或者至少改进,因为我完全不熟悉线程,我不知道如何用线程再次将结果作为字符串返回...
有人可以帮忙吗。
感谢
编辑:
这是在Windows 7上运行的c#winform应用程序。 基本上这个想法是调用cmd命令并运行命令...... 这是从visual studio运行时出现的错误:
The CLR has been unable to transition from COM context 0x8d85c0 to COM context 0x8d8730 for 60 seconds. The thread that owns the destination context/apartment is most likely either doing a non pumping wait or processing a very long running operation without pumping Windows messages. This situation generally has a negative performance impact and may even lead to the application becoming non responsive or memory usage accumulating continually over time. To avoid this problem, all single threaded apartment (STA) threads should use pumping wait primitives (such as CoWaitForMultipleHandles) and routinely pump messages during long running operations.
编辑2 :: 好的,这是我到目前为止所做的事情
public string ExecuteCommandSync(object command)
{
string result = "";
try
{
backgroundWorker1.RunWorkerAsync(command);
}
catch (Exception objException)
{
MessageBox.Show("error : " + objException.Message);
}
return result;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
string result;
Thread.Sleep(300);
object command = (object)e.Argument;
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
proc.Start();
result = proc.StandardOutput.ReadToEnd();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
results = (string)e.Result;
}
然后我用它来调用它:
string result1 = ExecuteCommandSync(command);
答案 0 :(得分:4)
result = proc.StandardOutput.ReadToEnd();
这是导致主UI线程挂起的语句。在您开始的进程停止运行之前,ReadToEnd()调用将不会完成。 “CLR已无法从COM上下文转换...”消息只是一个警告,当调试器也注意到您的主线程已经死亡时触发。它猜测它可能是由死锁造成的。
线程确实是您的解决方案,只需将此代码移动到BackgroundWorker的DoWork事件处理程序中即可。请阅读this MSDN page获取指导。
答案 1 :(得分:2)
添加到您的计划中:
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
还有:
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
string result = (string)e.Result;
//do what you need with it.
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
//do your work here
e.Result = yourResult;
}
但是还要记住别人说的话:线程不会比非线程程序运行得更快。好处是程序不会“挂起”。
答案 2 :(得分:0)
您可以使用活动。当你的thead完成后,它会抛出一个事件并将String赋予事件。
答案 3 :(得分:0)
另一个线程不会让它运行得更快,因为等待应用程序执行某些操作所花费的时间并不受哪个步骤的影响。
然而,这不是您的问题,您的问题是 UI线程花费的时间太长。非UI线程可以在不触发该错误的情况下花费数年时间来做某事,因此它确实可以解决问题。
另一种方法是不执行ReadToEnd()
,而是在它们到来时读取和处理较小的块。根据您调用的程序的性质,这可以解决您的所有问题(如果程序开始快速响应,并且您有这样的延迟的原因是它发送了大量数据到输出)或不(如果程序花了几分钟发送一个字节,那么你遇到了和以前一样的问题。
这两个可以合并,另一个线程一次从被调用程序的标准输出读取块,并在其进行时相应地更新状态。