在asp.net中实时显示命令行程序的输出

我正在编写一个Web应用程序,其中应用程序使用System.Diagnostics类在系统上运行命令。 我想从命令中显示实时输出,这需要花费很多时间才能完成。 搜索了一下之后,我发现BeginOutputReadLine可以将输出流式传输到事件处理程序。

我也使用jquery ajax来调用此方法并使进程异步运行。 到目前为止,我试图这样做:

Process p2= new Process(); p2.OutputDataReceived += new DataReceivedEventHandler(opHandler); p2= Process.Start (psi2);
p2.BeginOutputReadLine();

我已经声明了一个带有静态变量的类来存储命令的输出,因为页面上的Label不能从静态方法访问。

 public class ProcessOutput { public static string strOutput; [WebMethod] public static string getOutput() { return strOutput; } } 

在BeginOutputReadLine的事件处理程序中,使用输出中的行设置变量。

 private static void opHandler(object sendingProcess,DataReceivedEventArgs outLine) { if (!String.IsNullOrEmpty(outLine.Data)) { ProcessOutput.strOutput= outLine.Data; } } 

从aspx页面,我调用方法来获取strOutput的值

  $(document).ready(function() { setInterval(function() { $.ajax({ type: "GET", url: "newscan.aspx/getOutput", data: "", success: function(msg){ $('#txtAsyncOp').append(msg.d); } }); }, 1000); }); 

我不知道为什么,但标签没有得到更新。 如果我发出警报,我每隔10秒就会在警报框中显示“未定义”。 任何人都可以建议我如何正确地做到这一点?

每个请求都开始一个新线程作为Request管道的一部分。 这是设计的。 每个线程都有自己的堆栈,无法访问其他堆栈。 当一个线程开始运行一个新方法时,它将该方法中的参数和局部变量存储在它自己的堆栈上。 简而言之,您将无法分配该变量并期望从另一个请求中检索其值。

您可以采取几种方法,可以将其范围扩展到会话变量(最常见):

 System.Web.HttpContext.Current.Session["variable"] = value ; 

或者使用以下方法将其设置为应用范围:

 if (System.Web.Caching.Cache["Key1"] == null) System.Web.Caching.Cache.Add("Key1", "Value 1", null, DateTime.Now.AddSeconds(60), Cache.NoSlidingExpiration, CacheItemPriority.High, onRemove); 

或者,您可以将输出记录到数据库或文件中,并通过WebMethod回显结果。 如果您的长时间运行进程异步运行,您将无法访问HttpContext – 因此会话状态包将不可用; 可以使用应用程序缓存,但是它通常不用于此类机制(缓存可用于性能原因,而不是持久性机制 – 重要的是要记住您无法控制Web应用程序何时回收)。

我强烈建议写入数据库或日志文件。 异步过程通常需要记录输出或跟踪来诊断潜在问题并validation结果。

此外,由于您无法控制Web应用程序何时回收,因此您很容易失去对正在启动的子进程的控制权。 更好的设计将启动进程内的异步方法 ,或者进程外的应用程序或服务,轮询数据库以获取作业(可能根据您的平台使用任务调度程序或cron)。