C# 管道能否在同一运行空间中并发运行?
如何在同一运行空间中并行运行两个cmdlet。我用的是C# 在两个线程中,我将使用相同的运行空间运行cmdletC# 管道能否在同一运行空间中并发运行?,c#,powershell,C#,Powershell,如何在同一运行空间中并行运行两个cmdlet。我用的是C# 在两个线程中,我将使用相同的运行空间运行cmdlet Pipeline pipeLine = powerShellRunspace.CreatePipeline(); pipeLine.Commands.Add(shellCommand); pipeLine.Input.Close(); pipeLine.Invoke(); pipeLine.Output.DataReady += new EventHandler(processDat
Pipeline pipeLine = powerShellRunspace.CreatePipeline();
pipeLine.Commands.Add(shellCommand);
pipeLine.Input.Close();
pipeLine.Invoke();
pipeLine.Output.DataReady += new EventHandler(processData); //processData is a method which processes data emitted by pipeline as and when it comes to avoid out of memory
if (pipeLine.Error != null && pipeLine.Error.Count > 0) {
Collection<Object> errors = (Collection<Object>)(pipeLine.Error.ReadToEnd());
//process those errors
}
Pipeline-Pipeline=powerShellRunspace.CreatePipeline();
pipeLine.Commands.Add(shell命令);
pipeLine.Input.Close();
pipeLine.Invoke();
pipeLine.Output.DataReady+=新的EventHandler(processData)//processData是一种处理管道发出的数据以避免内存不足的方法
if(pipeLine.Error!=null&&pipeLine.Error.Count>0){
集合错误=(集合)(pipeLine.Error.ReadToEnd());
//处理这些错误
}
但是当两个线程同时使用相同的运行空间来运行cmdlet时。我得到一个异常,“管道未执行,因为管道已经在执行。管道不能并发执行。”
出于性能原因,我需要使用相同的运行空间。如何实现我的目标?你看过这门课了吗?使用它和InitialSessionState可以帮助消除模块导入的开销,因为它只在每个池而不是每个运行空间中执行一次。如果您正在寻找powershell命令的异步执行,这里有一个非常基本的、不适合生产的示例:(注意,我不是在使用Visual Studio的计算机上,但这应该是正确的)
运行空间缺少支持并发性所需的同步。假设您的目标是“良好的性能”,您应该进一步说明为什么多个运行空间不能给您带来良好的性能。您好@JasonShirk,我的是web应用程序,因为我正在运行空间中导入powershell模块,当许多用户发出http请求时,速度会很慢。您知道如何在Runspacepool中进行错误处理吗?我必须绑定eventhandler以避免内存不足(更新了我的代码)…我遇到了同样的问题。有人尝试过这些解决方案并成功了吗@Praveen KumarHi@ch.smrutiranjanparida,我想我使用RunspacePool并将该池分配给PowerShell obj,使用powerShellObj.Streams.Error进行错误处理,并使用powerShellObj.BeginInvoke将PSDataCollection传递给它,以处理PowerShell commandHi@StephenP发出的数据,但是如何在使用RunspacePool时处理错误,我已经更新了我的代码,以展示如何在使用单个运行空间时处理错误。需要注意的是,我的是web应用程序,所以我不能同时异步运行所有powershell命令,powershell命令将在http请求发出时运行。在调用powershell命令之前,我应该绑定
pipeLine.Output.DataReady+=new EventHandler(processData)
处理管道发出的数据,以避免内存不足。在进行EndInvoke调用时,powershell命令引发的错误将作为运行时错误被拾取。您需要添加错误处理逻辑。您还可以检查和属性。您仍然可以使用runspacepool来消除模块导入的一些开销,您只需要实现runspacepool的缓存。@StephenP我认为您不能在迭代字典时修改它。应该将toBeRemoved添加到要删除的项集合中,然后从foreach循环之外的字典中删除该集合中的每个项(sleep语句所在的位置)。否则我很肯定你会得到一个例外。@ksun接得好。我把}放错地方了。if(toBeRemoved)应该在foreach循环之后。我在thread.sleep调用之前有一个},而不是if(toBeRemoved)。我已经更新了答案。
Pipeline pipeLine = powerShellRunspace.CreatePipeline();
pipeLine.Commands.Add(shellCommand);
pipeLine.Input.Close();
pipeLine.Invoke();
pipeLine.Output.DataReady += new EventHandler(processData); //processData is a method which processes data emitted by pipeline as and when it comes to avoid out of memory
if (pipeLine.Error != null && pipeLine.Error.Count > 0) {
Collection<Object> errors = (Collection<Object>)(pipeLine.Error.ReadToEnd());
//process those errors
}
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.AuthorizationManager = new AuthorizationManager("MyShellId");
iss.ImportPSModule(new string[] { "MSOnline" });
#set commands we want to run concurrently
string[] commands = new string[4] {
"Start-Sleep -Seconds 5; 'Hi from #1'",
"Start-Sleep -Seconds 7; 'Hi from #2'",
"Start-Sleep -Seconds 3; 'Hi from #3'",
"throw 'Danger Will Robinson'"
};
Dictionary<PowerShell, IAsyncResult> dict = new Dictionary<PowerShell, IAsyncResult>();
//this loads the InitialStateSession for all instances
//Note you can set the minimum and maximum number of runspaces as well
using(RunspacePool rsp = RunspaceFactory.CreateRunspacePool(iss))
{
rsp.SetMinRunspaces(5);
rsp.SetMaxRunspaces(10);
rsp.Open();
foreach(string cmd in commands)
{
PowerShell ps = PowerShell.Create();
ps.AddScript(cmd);
ps.RunspacePool = rsp;
//Add parameters if needed with ps.AddParameter or ps.AddArgument
dict.Add(ps,ps.BeginInvoke());
}
do{
List<PowerShell> toBeRemoved = new List<PowerShell>();
foreach(KeyValuePair<PowerShell, IAsyncResult> kvp in dict)
{
if(kvp.Value.IsCompleted)
{
try
{
PSDataCollection<PSObject> objs = kvp.Key.EndInvoke(kvp.Value);
foreach(PSObject obj in objs)
{
Console.WriteLine(obj);
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
toBeRemoved.Add(kvp.Key);
}
}
}
foreach(PowerShell item in toBeRemoved)
{
dict.Remove(item);
}
//Wait before we check again
Thread.Sleep(200);
} while (dict.Count > 0)
rsp.Close();
}
//Added to keep console open
Console.Read();
Hi from #3
Hi from #1
Hi from #2