如何创建和执行行动队列<task <bool>&gt; </task <bool>

时间:2014-03-09 15:44:44

标签: c# asynchronous callback queue async-await

我正在寻找创建异步回调机制,感兴趣的各方可以注册一个或多个回调方法。

我想触发并await完成队列中的所有Actions,并确定其中任何一个是否已返回true

有人会对现有的库或模式有任何建议吗?

2 个答案:

答案 0 :(得分:1)

  

我想触发并等待队列中所有Actions的完成,并确定其中任何一个是否返回true。

如果你想同时调用它们并等待它们全部完成,那么就可以这样做:

IEnumerable<Func<Task<bool>>> queue = ...;
var results = await Task.WhenAll(queue.Select(x => x()));
return results.Any(x => x);

如果你想一次调用一个,那么就可以这样做:

IEnumerable<Func<Task<bool>>> queue = ...;
foreach (var callback in queue)
{
  if (await callback())
    return true;
}
return false;

答案 1 :(得分:0)

由于我不确定,您打算等待异步调用的完成,我只是稍微摆弄一下,并为您提供双向解决方案。

此解决方案提供了两种获取方法完成情况的方法......

  • ...通过任何方法完成时触发的Event(在EventArgs中提供MethodInfo和Result)
  • ...通过MethodInvokeState
  • 中的阻止getter

因此要实现它,您需要MethodCompletedEventArgs

public class MethodCompletedEventArgs : EventArgs
{
    private MethodInfo m_method;
    private Boolean m_result;
    public MethodCompletedEventArgs(MethodInfo mi, Boolean result)
    {
        m_method = mi;
        m_result = result;
    }
    public MethodInfo Method { get { return m_method; } }
    public Boolean Result { get { return m_result; } }
}

的对象
  • 持有目标代表
  • 返回结果(阻止)
  • 包围调用(以提供结果)

此处为MethodInvokeState

public class MethodInvokeState
{
    public MethodInvokeState(Func<bool> target)
    {
        m_target = target;
        m_mreCompleted = new ManualResetEvent(false);
        m_blnCompleted = false;
    }

    private Func<bool> m_target;
    private ManualResetEvent m_mreCompleted;
    private Boolean m_blnCompleted;
    private Boolean m_result;

    public Boolean WaitForCompletion()
    {
        if (!m_blnCompleted)
            m_mreCompleted.WaitOne();
        return m_result;
    }

    public Boolean Invoke()
    {
        m_result = m_target.Invoke();
        m_blnCompleted = true;
        m_mreCompleted.Set();
        return m_result;
    }
    public MethodInfo Method { get { return m_target.Method; } }

}

最后,您需要具有以下属性的Scheduler:

  • 它可以注册MethodInvokeState个对象(将它们排队)
  • 可以启动它(使它使方法出列并调用它们)
  • 可以暂停(中止调用过程)
  • 它提供MethodCompleted事件(使用上述EventArgs)

此处为MethodScheduler

public class MethodScheduler
{
    public MethodScheduler()
    {
        m_qAction = new Queue<MethodInvokeState>();
        m_mreNewAction = new ManualResetEvent(false);
        m_objQueueLock = new Object();
        m_blnClosing = false;
    }
    private Queue<MethodInvokeState> m_qAction;
    private ManualResetEvent m_mreNewAction;
    private Object m_objQueueLock;
    private Thread m_trdInvoker;
    private Boolean m_blnInvoking;
    private Boolean m_blnClosing;
    public delegate void MethodCompletedEventHandler(Object sender, MethodCompletedEventArgs e);
    public event MethodCompletedEventHandler MethodCompleted;        

    public void Init()
    {
        m_trdInvoker = new Thread(new ThreadStart(__invoker));
        m_blnInvoking = true;
        m_trdInvoker.Start();
    }

    private void __invoker()
    {
        while (m_blnInvoking)
        {
            int count = 0;
            lock (m_objQueueLock)
            {
                if((count = m_qAction.Count) == 0) 
                {
                    m_mreNewAction.Reset();                        
                }
            }
            if (count == 0) m_mreNewAction.WaitOne();
            if (!m_blnClosing)
            {
                MethodInvokeState p = m_qAction.Dequeue();

                bool result = p.Invoke();
                if (MethodCompleted != null)
                    MethodCompleted(p, new MethodCompletedEventArgs(p.Method, result));                                       
            }
        }
    }

    public void Stop()
    {
        m_blnInvoking = false;
        m_blnClosing = true;
        m_mreNewAction.Set();
    }

    public void RegisterMethod(MethodInvokeState p) {
        if (!m_blnInvoking) throw new InvalidOperationException("Cannot register a method if invoker is not initialized");
        Console.WriteLine(" * MethodScheduler: Registering Method: " +  p.Method.Name); 
        lock (m_objQueueLock)
        {
            m_qAction.Enqueue(p);
            m_mreNewAction.Set();
        }
    }      
}

最后这里有一个如何使用它的例子:

class Program
{
    static void Main(string[] args)
    {
        MethodScheduler ms = new MethodScheduler();
        ms.Init();
        ms.MethodCompleted += MethodCompletedHandler;

        MethodInvokeState mtA = new MethodInvokeState(new Func<bool>(SomeMethodA));
        MethodInvokeState mtB = new MethodInvokeState(new Func<bool>(SomeMethodB));

        ms.RegisterMethod(mtA);
        ms.RegisterMethod(mtB);

        Console.WriteLine(" * SENDER: Waiting for completion (SomeMethodA) ...");
        bool result = mtA.WaitForCompletion();
        Console.WriteLine(" * SENDER: SomeMethodA completed: " + result);

        Console.WriteLine(" * SENDER: Waiting for completion (SomeMethodB) ...");
        result = mtB.WaitForCompletion();
        Console.WriteLine(" * SENDER: SomeMethodB completed: " + result);

        Console.WriteLine("Press any key to exit ...");
        Console.ReadKey();
        ms.Stop();
    }

    public static void MethodCompletedHandler(Object sender, MethodCompletedEventArgs e)
    {
        Console.WriteLine(" * HANDLER: Method '{0}' completed with: {1} " , e.Method.Name, e.Result.ToString());
    }

    public static bool SomeMethodA()
    {
        Console.WriteLine(" * SomeMethodA: will succeed in 5 seconds!");
        Thread.Sleep(5000);
        return true;
    }
    public static bool SomeMethodB()
    {
        Console.WriteLine(" * SomeMethodB: will fail in 3 seconds!");
        Thread.Sleep(3000);
        return false;
    }
}

我认为代码是安静的自我解释。如果仍有问题,请发表评论。