在rx中你可以写:
var oe = Observable.FromEventPattern<SqlNotificationEventArgs>(sqlDep, "OnChange");
然后订阅observable以将sqlDep对象上的OnChange事件转换为observable。
类似地,如何使用任务并行库从C#事件创建任务?
编辑:澄清 Drew指向的解决方案然后由user375487明确地书写,适用于单个事件。任务一完成......好了就完了。
可观察事件可以随时再次触发。它可以被视为一个可观察的流。 TPL数据流中的一种ISourceBlock。但是在文档http://msdn.microsoft.com/en-us/library/hh228603(v=vs.110).aspx中没有ISourceBlock的例子。
我最终找到了一篇论坛帖子,解释了如何做到这一点:http://social.msdn.microsoft.com/Forums/en/tpldataflow/thread/a10c4cb6-868e-41c5-b8cf-d122b514db0e
public static ISourceBlock CreateSourceBlock(
动作,行动,行动,ISourceBlock&GT;执行人)
{
var bb = new BufferBlock();
执行者(t =&gt; bb.Post(t),()=&gt; bb.Complete(),e =&gt; bb.Fault(e),bb);
返回bb;
}
//Remark the async delegate which defers the subscription to the hot source.
var sourceBlock = CreateSourceBlock<SomeArgs>(async (post, complete, fault, bb) =>
{
var eventHandlerToSource = (s,args) => post(args);
publisher.OnEvent += eventHandlerToSource;
bb.Complete.ContinueWith(_ => publisher.OnEvent -= eventHandlerToSource);
});
我没试过上面的代码。异步委托和CreateSourceBlock的定义之间可能存在不匹配。
答案 0 :(得分:1)
没有与TPL中的事件异步模式(EAP)直接等效。你需要做的是使用你在事件处理程序中发出信号的TaskCompletionSource<T>
。 Check out this section on MSDN示例使用WebClient :: DownloadStringAsync来演示模式。
答案 1 :(得分:1)
您可以使用TaskCompletionSource。
public static class TaskFromEvent
{
public static Task<TArgs> Create<TArgs>(object obj, string eventName)
where TArgs : EventArgs
{
var completionSource = new TaskCompletionSource<TArgs>();
EventHandler<TArgs> handler = null;
handler = new EventHandler<TArgs>((sender, args) =>
{
completionSource.SetResult(args);
obj.GetType().GetEvent(eventName).RemoveEventHandler(obj, handler);
});
obj.GetType().GetEvent(eventName).AddEventHandler(obj, handler);
return completionSource.Task;
}
}
使用示例:
public class Publisher
{
public event EventHandler<EventArgs> Event;
public void FireEvent()
{
if (this.Event != null)
Event(this, new EventArgs());
}
}
class Program
{
static void Main(string[] args)
{
Publisher publisher = new Publisher();
var task = TaskFromEvent.Create<EventArgs>(publisher, "Event").ContinueWith(e => Console.WriteLine("The event has fired."));
publisher.FireEvent();
Console.ReadKey();
}
}
编辑根据您的说明,以下是如何使用TPL DataFlow实现目标的示例。
public class EventSource
{
public static ISourceBlock<TArgs> Create<TArgs>(object obj, string eventName)
where TArgs : EventArgs
{
BufferBlock<TArgs> buffer = new BufferBlock<TArgs>();
EventHandler<TArgs> handler = null;
handler = new EventHandler<TArgs>((sender, args) =>
{
buffer.Post(args);
});
buffer.Completion.ContinueWith(c =>
{
Console.WriteLine("Unsubscribed from event");
obj.GetType().GetEvent(eventName).RemoveEventHandler(obj, handler);
});
obj.GetType().GetEvent(eventName).AddEventHandler(obj, handler);
return buffer;
}
}
public class Publisher
{
public event EventHandler<EventArgs> Event;
public void FireEvent()
{
if (this.Event != null)
Event(this, new EventArgs());
}
}
class Program
{
static void Main(string[] args)
{
var publisher = new Publisher();
var source = EventSource.Create<EventArgs>(publisher, "Event");
source.LinkTo(new ActionBlock<EventArgs>(e => Console.WriteLine("New event!")));
Console.WriteLine("Type 'q' to exit");
char key = (char)0;
while (true)
{
key = Console.ReadKey().KeyChar;
Console.WriteLine();
if (key == 'q') break;
publisher.FireEvent();
}
source.Complete();
Console.ReadKey();
}
}