c# - 从单独的线程更新 cmdlet 进度的最佳方法

标签 c# .net multithreading powershell powershell-cmdlet

我有一个用 C# 编写的 powershell cmdlet(源自 PSCmdlet ),它将启动一个长时间运行的任务,该任务应使用 WriteProgress() 更新其进度。当它运行时。由于powershell不允许单独的线程使用WriteObjectWriteProgress我必须创建一个 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/

相关文章:

c# - 解析具有多个对象的 Json newtonsoft

c# - 如何增加单选按钮之间的间距

c# - 除非标记为UNSAFE,否则C#CLR会引发安全异常

android - 在线程中的小部件中显示 Toast

c++ - 删除 std::thread 指针引发异常 "libc++abi.dylib: terminating"

multithreading - 在Visual Studio Express 2010中进行调试时如何列出线程

c# - 如何检测窗口是否闪烁

c# - TableAdapter.update方法,到哪里去了?

c# - 如何使用 String.Format (c#) 去掉小数部分

c# - 哪种是为应用程序编写日志的最基于性能的方法