我正在寻找创建异步回调机制,感兴趣的各方可以注册一个或多个回调方法。
我想触发并await
完成队列中的所有Actions
,并确定其中任何一个是否已返回true
。
有人会对现有的库或模式有任何建议吗?
答案 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
因此要实现它,您需要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;
}
}
我认为代码是安静的自我解释。如果仍有问题,请发表评论。