如何在C#或类似框架中按顺序运行事件
如何取消/调整与另一个线程中的同一事件并行执行的事件 例如,在文本框中,每次输入字符时,如果定义了文本更改事件,则会触发事件。但是在输入第一个字符之后,事件(让我们称为第一个事件)需要很多时间(因为将有更多字符串与单个字符匹配),并执行一些操作,如更改标题标签的内容。输入第二个字符后,引发并行运行的新事件花费的时间更少。现在,在输入第二个字符后触发的第二个事件执行得很快,返回第一个,第一个事件最后执行,因此,第一个事件的结果将最终打印在标签上,而不是第二个 是否有更好的方法在开始第二个事件之前取消第一个事件。我想到的一件事是在全局列表变量上注册线程,并在开始执行之前杀死所有未死亡的线程。这行吗??有没有更好的办法来处理这种情况如何在C#或类似框架中按顺序运行事件,c#,multithreading,events,C#,Multithreading,Events,如何取消/调整与另一个线程中的同一事件并行执行的事件 例如,在文本框中,每次输入字符时,如果定义了文本更改事件,则会触发事件。但是在输入第一个字符之后,事件(让我们称为第一个事件)需要很多时间(因为将有更多字符串与单个字符匹配),并执行一些操作,如更改标题标签的内容。输入第二个字符后,引发并行运行的新事件花费的时间更少。现在,在输入第二个字符后触发的第二个事件执行得很快,返回第一个,第一个事件最后执行,因此,第一个事件的结果将最终打印在标签上,而不是第二个 是否有更好的方法在开始第二个事件之前取
另外,我知道搜索可以在空间或进入后启动,以解决此特定问题。但我想你已经注意到了我的要点 NET
Task
API内置了取消的概念。有关示例和更多信息的链接,请参见本页 我最喜欢的处理这个确切问题的库是Rx.Net
和TPL
。使用Observable.fromsync
一些代码
var textChanged = Observable.FromEventPattern(x => textBox.TextChanged += x, x => textBox.TextChanged -= x)
.Select(_ => textBox.Text);
IDisposable eventHandler = textChanged.Throttle(TimeSpan.FromMilliseconds(500))
.Select(text => Observable.FromAsync((TaskCancelationToken cancel) => DoSearchTaskAsync(text, cancel)))
.Switch()
.Subscrible(results =>
{
//Update the UI
});
请注意,没有必要显式键入任何此类内容…我这样做只是为了清楚起见,但我很可能键入了一两个类名
编辑
搜索方法将是任务DoSearchTaskAsync(string,TaskCancellationToken)
的方法体
神奇的酱汁来自Observable.fromsync
和Observable.Switch
每次我们在文本框中进行更改时,我们都会触发一个事件。这是由.Throttle
过滤的(如您所料)。聪明的一点是,我们随后使用Observable.fromsync
在DoSearchTaskAsync
上创建一个新的事件源。在这一点上,我们有一个IObservable
,或者用另一种方式,一个eventsource的eventsource。切换意味着我们只需要outter eventsource中最近发送的eventsource的结果,并终止(处置)先前eventsource的订阅
当我们订阅新的任务时,处理以前的可见.fromsync
的行为将导致任务取消令牌
取消,并防止其结果冒泡
所有这些都是非常聪明的东西,我只是最近才发现这个令人敬畏的模式(如果我可以的话,我会相信作者)
至于可观察的。FromEventPattern
这是非常不幸的,从C#5开始,没有一流的事件处理程序,所以我们传入一个lambda用于订阅,一个lambda用于取消订阅。我将研究如何操作事件流,与任务并行库一起…由于UI是单线程,因此事件始终按其自身顺序排列。@FelicePollano,但不一定是由事件启动的回调的结果。例如,如果用户键入“abc”,但您的客户端缓存了“abc”而不是“ab”的搜索结果,则UI可以使用“abc”的结果进行更新,然后是“ab”的结果。不太理想。如果不是太麻烦的话,你能给我解释一下代码吗??我对这东西有点陌生。提前谢谢。。我要找的东西是,1。在哪里绑定此事件??2.我的搜索操作方法在哪里被调用?(DoSearchTaskAsync???)3。它如何取消以前调用的事件??它需要参考这些方法,对吗??提前谢谢我刚看到你的编辑。。。刷新后:)谢谢:)@sriharshaKB我确实编辑了我的答案。这是我能做的最好的了。不幸的是,在理解我所写的解释之前,您需要在Rx.Net中有一个良好的基础。我想到了这一点。但我刚才提到了线程解决方案,因为两者都是相似的。嗯,我不完全知道。但在某种程度上,我们是在用自己的双手处理这个问题。还有其他解决方案吗??而且必须以某种方式调用内置的取消。然后我们可以将它绑定到一个变量,如果它为false,则停止执行。在这种情况下,我们可以将任务绑定到该变量。当下一个字符出现时,事件激发,变量将设置为false触发所有任务的结束。。然后,我们稍后再次将其设置为true,并再次将新任务绑定到该变量。听起来像科幻小说??)