事件上的C#PowerShell Cmdlet WriteObject

本文关键字:Cmdlet WriteObject C#PowerShell 事件 | 更新日期: 2023-09-27 18:27:43

我扩展了System.Collections.Concurrent.CurrentQueue,以便在对象入队时引发事件。我现在需要能够使用System.Management.Automation.WriteObject/WriteVerbose/WriteDebug方法来写入上述事件中的对象。但是,当尝试在事件处理程序中使用System.Management.Automation.WriteObject/WriteVerbose/WriteDebug时,我收到以下错误。

有人知道我如何将事件封送回主线程,以便使用System.Management.Automation.WriteObject/WriteVerbose/WriteDebug方法吗?

这是我的扩展并发队列类。

public class ConcurrentQueueEx<T> : ConcurrentQueue<T>
{
    #region Private Variables
    private Guid _id;
    #endregion
    #region Public Accessors
    public Guid Id
    {
        get { return this._id; }
    }
    #endregion
    #region Event Declarations
    public event PSObjectAddedEventHandler PSObjectAdded;
    protected virtual void OnPSObjectAdded(Guid parentId, object obj)
    {
        PSObjectAddedEventHandler handler = PSObjectAdded;
        if (handler != null)
        {
            PSObjectAddedEventArgs oae = new PSObjectAddedEventArgs();
            oae._ParentId = parentId;
            oae._Object = obj;
            handler(oae);
        }
    }
    #endregion
    #region Public Functions
    public new virtual void Enqueue(T item)
    {
        base.Enqueue(item);
        OnPSObjectAdded(this._id, item);
    }
    public virtual void Push(T item)
    {
        base.Enqueue(item);
        OnPSObjectAdded(this._id, item);
    }
    public virtual T Pop()
    {
        T obj;
        base.TryDequeue(out obj);
        return obj;
    }
    #endregion
}

以下是cmdlet的相关部分。

protected override void BeginProcessing()
    {
        base.BeginProcessing();
        _messageQueue = new ConcurrentQueueEx<object>();
        _messageQueue.PSObjectAdded += _messageQueue_PSObjectAdded;
        _resultQueue = new ConcurrentQueueEx<object>();
        _resultQueue.PSObjectAdded += _resultQueue_PSObjectAdded;
    }
private void _resultQueue_PSObjectAdded(PSObjectAddedEventArgs e)
    {
        WriteObject(e._Object);
    }
    private void _messageQueue_PSObjectAdded(PSObjectAddedEventArgs e)
    {
        WriteVerbose(e._Object.ToString());
    }

以下是异常详细信息。

System.Management.Automation.PSInvalidOperationException was unhandled by user code
HResult=-2146233079
Message=The WriteObject and WriteError methods cannot be called from outside the overrides of the BeginProcessing, ProcessRecord, and EndProcessing methods, and they can only be called from within the same thread. Validate that the cmdlet makes these calls correctly, or contact Microsoft Customer Support Services.
Source=System.Management.Automation

事件上的C#PowerShell Cmdlet WriteObject

当引发事件的线程排队时,"主线程"在做什么?

如果主线程被阻塞,那么您可以让它等待同步对象,然后让它将对象出列。

如果线程正在做其他事情,那么您需要它来中断它(比如说一个事件),或者让它轮询队列。我想你会想做第一个。在这种情况下,您需要在cmdlet中注册一个事件,然后从其他线程激发该事件。这里的第二个答案显示了如何做到这一点。