gpt4 book ai didi

c# - 从事件处理程序报告 Powershell 进度

转载 作者:太空宇宙 更新时间:2023-11-03 12:42:28 24 4
gpt4 key购买 nike

我用 C# 编写了一个 cmdlet,它充当繁重/长时间运行的同步操作的包装器。该方法(其他人的代码)通过事件处理程序报告此长时间运行操作期间的进度百分比,我想将这些连接到 powershell 的标准 WriteProgress 方法以获得 pretty-print 进度条.但是,我收到以下错误消息:

WriteObject 和 WriteError 方法不能从 BeginProcessing、ProcessRecord 和 EndProcessing 方法的覆盖之外调用,它们只能在同一线程内调用。

这是我的代码:

overrride void ProcessRecord()
{
LongRunningOperation op = new LongRunningOperation();
op.ProgressChanged += ProgressUpdate;
op.Execute();
op.ProgressChanged -= ProgressUpdate;
}

void ProgressUpdate(object sender, ProgressChangeEventArgs e)
{
ProgressRecord progress = new ProgressRecord(activityId: 1, activity: "Moving data", statusDescription: "Current operation");
progress.PercentComplete = e.ProgressPercentage;
WriteProgress(progress);
}

有人能发现我做错了什么吗?

更新:看起来事件处理程序是从不同于 ProcessRecord() 的线程触发的。如何将我需要的信息返回到与 ProcessRecord() 相同的线程中?

最佳答案

您需要手动编码 ProgressChanged事件处理程序返回到 PowerShell 管道线程。这可以通过应用生产者-消费者模式来完成,其中 ProgressChanged事件处理程序将成为生产者,PowerShell 管道线程中的事件循环将成为消费者。在 BlockingCollection<T> 的支持下可以轻松实现在 .NET Framework 4.0 中引入:

overrride void ProcessRecord() {
Task longRunningOperation;
using(BlockingCollection<ProgressRecord> queue = new BlockingCollection<ProgressRecord>()) {
//offload LongRunningOperation to different thread to keep control on PowerShell pipeline thread
longRunningOperation=Task.Run(() => {
try {
//replace EventHandler<ProgressChangeEventArgs> with ProgressChanged type
EventHandler<ProgressChangeEventArgs> handler =
//implemented as anonymous method to capture queue local variable
(object sender, ProgressChangeEventArgs e) => {
ProgressRecord progress = new ProgressRecord(activityId: 1, activity: "Moving data", statusDescription: "Current operation");
progress.PercentComplete = e.ProgressPercentage;
//queue ProgressRecord for processing in PowerShell pipeline thread
queue.Add(progress);
}
LongRunningOperation op = new LongRunningOperation();
op.ProgressChanged += handler;
op.Execute();
op.ProgressChanged -= handler;
} finally {
queue.CompleteAdding();
}
});
//event loop
for(;;) {
ProgressRecord progress;
if(!queue.TryTake(out progress, Timeout.Infinite)) {
break;
}
WriteProgress(progress);
}
}
//get any exception from LongRunningOperation
longRunningOperation.GetAwaiter().GetResult();
}

关于c# - 从事件处理程序报告 Powershell 进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38405770/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com