我的应用程序是用c#编写的,并使用Powershell类的.net库。它是多线程的,可以在runspacepool上同时执行一堆powershell脚本。 我使用的runspacepool大小为100.在执行每个脚本之前,我使用下面的代码创建一个到目标计算机的会话。 我使用BeginInvoke开始在管道中执行,并使用end-invoke来获取结果,包括会话。
ps = PowerShell.Create()
var sessionScript = new PSCommand();
sessionScript.AddCommand(New-PSSession);
sessionScript.AddParameter("ConnectionUri", "http://192.xxx.x.xxx:5985";);
sessionScript.AddParameter("AllowRedirection");
var sessOpt = new System.Management.Automation.Remoting.PSSessionOption();
sessOpt.OpenTimeout = new TimeSpan(0,0,0,0, 120000);
sessOpt.CancelTimeout = new TimeSpan(0, 0, 0, 0,120000);
sessionScript.AddParameter("SessionOption", sessOpt);
var cred = new PSCredential(uName, password);
sessionScript.AddParameter("Credential", cred);
ps.Commands = sessionScript
ps.RunSpacePool = mypool ## size 100 created earlier
asyncResult = ps.BeginInvoke();
resultsOut = ps.EndInvoke(asyncResult);
当我将并行执行会话数保持在100以下时,一切都很好。偶尔当我达到100及以上时,我注意到一两个线程(.net任务)被卡住了。我做了一些调试,发现线程被EndInvoke卡住了。即使在一周之后,电话也没有返回,线程仍然存在。
因此,我通过向此操作添加Timer来替换执行代码
Timer taskTimer = new Timer(TaskHitTimeout, null , 120000, System.Threading.Timeout.Infinite);
asyncResult = ps.BeginInvoke();
while (true)
{
if (asyncResult.IsCompleted || this.isCancelled)
break;
Thread.Sleep(200);
}
if (!this.isCancelled)
resultsOut = ps.EndInvoke(asyncResult);
在TimerHandler中我将isCancelled设置为True
private void TaskHitTimeout(Object statusCode)
{ this.isCancelled = True;}
这确实解决了我的问题。但我想了解为什么对EndInvoke的调用不会返回。我还能做些什么来改善这一点。如果其他人看到了类似的问题。