我有一个用 C# 编写的 powershell cmdlet(源自 PSCmdlet
),它将启动一个长时间运行的任务,该任务应使用 WriteProgress()
更新其进度。当它运行时。由于powershell不允许单独的线程使用WriteObject
或WriteProgress
我必须创建一个 Queue<object>
在主线程中,我将要写入管道/进度的任务中的项目添加到队列中。 while 循环将在对象进入并写入管道/进度条时将其出列。
这是可行的,但我想看看是否有更好的使用 C#/VB 编写的 powershell cmdlet 进行多线程的实践。例如,使用 WPF,我始终可以使用 UIComponent.Dispatcher.Invoke()
进入 UI 线程。如果我需要更新进度条或 UI 组件。有什么等效的东西可以用来“步入”powershell 线程来更新 UI 或写入管道吗?
最佳答案
这里是封装在类中的队列系统的示例,因此它更易于使用并模仿 Cmdllet.WriteObject 的行为。这样,您可以从单独的线程中调用 WriteObject,该对象将被编码到 powershell 线程上并写入管道。
[Cmdlet("Test", "Adapter")]
public class TestCmdlet : PSCmdlet
{
protected override void ProcessRecord()
{
PowerShellAdapter adapter = new PowerShellAdapter(this, 100);
Task.Factory.StartNew(() => {
for (int x = 0; x < 100; x++) {
adapter.WriteObject(x);
Thread.Sleep(100);
}
adapter.Finished = true;
});
adapter.Listen();
}
}
<小时/>
public class PowerShellAdapter
{
private Cmdlet Cmdlet { get; set; }
private Queue<object> Queue { get; set; }
private object LockToken { get; set; }
public bool Finished { get; set; }
public int Total { get; set; }
public int Count { get; set; }
public PowerShellAdapter(Cmdlet cmdlet, int total)
{
this.Cmdlet = cmdlet;
this.LockToken = new object();
this.Queue = new Queue<object>();
this.Finished = false;
this.Total = total;
}
public void Listen()
{
ProgressRecord progress = new ProgressRecord(1, "Counting to 100", " ");
while (!Finished || Queue.Count > 0)
{
while (Queue.Count > 0)
{
progress.PercentComplete = ++Count*100 / Total;
progress.StatusDescription = Count + "/" + Total;
Cmdlet.WriteObject(Queue.Dequeue());
Cmdlet.WriteProgress(progress);
}
Thread.Sleep(100);
}
}
public void WriteObject(object obj)
{
lock (LockToken)
Queue.Enqueue(obj);
}
}
关于c# - 从单独的线程更新 cmdlet 进度的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12852494/