System.Threading.Timer 杀死 PowerShell 控制台
Posted
技术标签:
【中文标题】System.Threading.Timer 杀死 PowerShell 控制台【英文标题】:System.Threading.Timer kills the PowerShell console 【发布时间】:2018-12-14 23:37:24 【问题描述】:当我在 PowerShell 控制台中运行它时:
$callback = [System.Threading.TimerCallback]
param($state)
$timer = [System.Threading.Timer]::new($callback, $null,
[timespan]::Zero,
[timespan]::FromSeconds(1))
然后一旦$callback
被调用(我确定这是根本原因,通过将dueTime
constructor's parameter 从[timespan]::Zero
更改为更长的延迟),整个控制台进程崩溃,说powershell has stopped working
。
可能是什么原因?我该如何克服呢?
【问题讨论】:
【参考方案1】:错误是:
在此线程中没有可用于运行脚本的运行空间。你可以 在 DefaultRunspace 属性中提供一个 System.Management.Automation.Runspaces.Runspace 类型。
而源于
System.Management.Automation.ScriptBlock.GetContextFromTLS()
委托是问题所在。这就是我的工作方式:
$helper = @'
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Management.Automation.Runspaces;
public class RunspacedDelegateFactory
public static Delegate NewRunspacedDelegate(Delegate _delegate, Runspace runspace)
Action setRunspace = () => Runspace.DefaultRunspace = runspace;
return ConcatActionToDelegate(setRunspace, _delegate);
private static Expression ExpressionInvoke(Delegate _delegate, params Expression[] arguments)
var invokeMethod = _delegate.GetType().GetMethod("Invoke");
return Expression.Call(Expression.Constant(_delegate), invokeMethod, arguments);
public static Delegate ConcatActionToDelegate(Action a, Delegate d)
var parameters =
d.GetType().GetMethod("Invoke").GetParameters()
.Select(p => Expression.Parameter(p.ParameterType, p.Name))
.ToArray();
Expression body = Expression.Block(ExpressionInvoke(a), ExpressionInvoke(d, parameters));
var lambda = Expression.Lambda(d.GetType(), body, parameters);
var compiled = lambda.Compile();
return compiled;
'@
add-type -TypeDefinition $helper
$runspacedDelegate = [RunspacedDelegateFactory]::NewRunspacedDelegate($callback, [Runspace]::DefaultRunspace)
$timer = [System.Threading.Timer]::new(
$runspacedDelegate,
$null,
[timespan]::Zero,
[timespan]::FromSeconds(1))
我借用了 NewRunspacedDelegate
https://www.powershellgallery.com/packages/ContainerTools/0.0.1
【讨论】:
哇,大惊小怪……令人印象深刻,但不确定是否值得……为什么要这么难,只是为了派代表? 顺便说一句,你是如何设法得到这个错误的?控制台只是为我崩溃了。 记录在事件日志中。也就是说,全文错误是从 PowerShell 6 输出的。以上是关于System.Threading.Timer 杀死 PowerShell 控制台的主要内容,如果未能解决你的问题,请参考以下文章
为啥 System.Timers.Timer 能在 GC 中存活,而 System.Threading.Timer 不能?
System.Windows.Forms.TimerSystem.Timers.TimerSystem.Threading.Timer
如何在 C# 中创建计时器而不使用 System.Timers.Timer 或 System.Threading.Timer
System.Threading.Timer:它为啥讨厌我?