我在确保异步任务中事件的顺序方面遇到问题。从其继承其他异步任务的类具有以下功能,并在构造函数参数中采用EventHandlers(ExecutionProgress,ExecutionStarted,ExecutionCompleted):
public abstract Task Operation(IProgress<EventArgs> progress);
public virtual void Execute()
{
ExecuteAsync()
}
private void ReportProgress(EventArgs args)
{
if(ExecutionProgress != null) ExecutionProgress(this, args);
}
private async Task ExecuteAsync()
{
if(ExecutionStarted != null) ExecutionStarted(this, EventArgs.Empty)
await Operation(new Progress<EventArgs>(ReportProgress));
if(ExecutionCompleted != null) ExecutionCompleted(this, EventArgs.Empty)
}
现在在我的一个继承自异步任务的类中,我用以下内容覆盖了Operation:
public override async Task Operation(IProgress<EventArgs> progress)
{
// run the synchronous function in another thread
JobResults results = await Task.Run(() => worker.DoYourJob());
progress.Report(results);
}
尝试访问JobResults时,经常(但并非总是)运行此代码会在ExecutionCompleted事件处理程序中导致NullReference Exception。这是因为无论出于何种原因,写入成员变量的ExecutionProgress事件通常都会在ExecutionCompleted之后触发。我认为该标准没有说明事件排序,但是我正在寻找一个很好的解决方案来确保确定性排序。我只想在处理完所有ExecutionProgress事件后才触发ExecutionCompleted。
这里有什么好看的解决方案?在处理所有进度报告事件之前,有什么方法可以等待。
所有事件均按顺序触发。如果您的事件处理程序是异步的(似乎是这种情况),那么触发事件的代码将在启动事件处理程序后立即继续执行,而不是在它们完成时继续执行。
如果触发事件的代码无需在所有处理程序都完成之前继续进行,那么您需要重新构造此类,以便事件处理程序可以在完成时向此类指示某种方式。有任何数量的方式来做到这一点,从传递参数,使处理程序告诉它处理完成后的情况下,或者具有事件处理程序的签名返回Task
,而不是void
(你需要await
那些触发事件时的任务)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句