事件上的C#PowerShell Cmdlet WriteObject

时间:2015-12-22 01:14:09

标签: c# powershell cmdlet

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

有谁知道如何将事件编组回主线程,以便我可以使用System.Management.Automation.WriteObject / WriteVerbose / WriteDebug方法?

这是我扩展的ConcurrentQueue类。

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

1 个答案:

答案 0 :(得分:0)

在引发事件的线程排队时,“主线程”是做什么的?

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

如果线程没有执行其他操作,那么您需要让它中断(通过事件说出来)或者让它轮询队列。我假设你想要做第一个。在这种情况下,您需要在cmdlet中注册事件并从其他线程触发事件。第二个答案here显示了如何执行此操作。

相关问题