C# 按正确顺序从异步/等待函数触发事件

C# 按正确顺序从异步/等待函数触发事件,c#,events,design-patterns,asynchronous,async-await,C#,Events,Design Patterns,Asynchronous,Async Await,我无法确保异步任务中事件的顺序。从中继承其他异步任务的类具有以下函数,并在构造函数参数中采用事件处理程序(ExecutionProgress、ExecutionStarted、ExecutionCompleted): public abstract Task Operation(IProgress<EventArgs> progress); public virtual void Execute() { ExecuteAsync() } private void Repo

我无法确保异步任务中事件的顺序。从中继承其他异步任务的类具有以下函数,并在构造函数参数中采用事件处理程序(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)

}
公共抽象任务操作(IProgress progress);
公共虚拟空执行()
{
ExecuteAsync()
}
私有void报告进度(EventArgs args)
{
if(ExecutionProgress!=null)ExecutionProgress(this,args);
}
专用异步任务ExecuteAsync()
{
如果(ExecutionStarted!=null)ExecutionStarted(此,EventArgs.Empty)
等待操作(新进展(报告进展));
如果(ExecutionCompleted!=null)ExecutionCompleted(此,EventArgs.Empty)
}
现在,在我的一个从异步任务继承的类中,我使用以下内容重写操作:

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);
}
public override异步任务操作(IProgress progress)
{
//在另一个线程中运行同步函数
JobResults=wait Task.Run(()=>worker.DoYourJob());
进度报告(结果);
}
尝试访问作业结果时,经常(但并非总是)运行此代码会导致ExecutionCompleted事件处理程序中出现NullReference异常。这是因为写入成员变量的ExecutionProgress事件通常在ExecutionCompleted之后出于任何原因被触发。我认为标准没有提到事件排序,但我正在寻找一个好的解决方案来确保这里的确定性排序我只想在处理完所有ExecutionProgress事件后触发ExecutionCompleted。

这里有什么好看的解决方案?是否有办法等待所有进度报告事件处理完毕。

事件都按顺序触发。如果事件处理程序是异步的(似乎是这样),那么触发事件的代码将在启动事件处理程序时继续执行,而不是在事件处理程序完成时继续执行

如果在所有处理程序完成之前触发事件的代码不需要继续,那么您需要重新构造此类,以便事件处理程序能够在完成时向此类指示。有很多方法可以做到这一点,从在事件中传递允许处理程序在完成时告诉它的参数,到让事件处理程序的签名返回一个
任务
,而不是
无效
(触发事件时,您需要等待这些任务).

事件都是按顺序触发的。如果事件处理程序是异步的(似乎是这样),那么触发事件的代码将在启动事件处理程序时继续执行,而不是在事件处理程序完成时继续执行

如果在所有处理程序完成之前触发事件的代码不需要继续,那么您需要重新构造此类,以便事件处理程序能够在完成时向此类指示。有很多方法可以做到这一点,从在事件中传递允许处理程序在完成时告诉它的参数,到让事件处理程序的签名返回一个
任务
,而不是
无效
(触发事件时,您需要等待这些任务).

事件都是按顺序触发的。如果事件处理程序是异步的(似乎是这样),那么触发事件的代码将在启动事件处理程序时继续执行,而不是在事件处理程序完成时继续执行

如果在所有处理程序完成之前触发事件的代码不需要继续,那么您需要重新构造此类,以便事件处理程序能够在完成时向此类指示。有很多方法可以做到这一点,从在事件中传递允许处理程序在完成时告诉它的参数,到让事件处理程序的签名返回一个
任务
,而不是
无效
(触发事件时,您需要等待这些任务).

事件都是按顺序触发的。如果事件处理程序是异步的(似乎是这样),那么触发事件的代码将在启动事件处理程序时继续执行,而不是在事件处理程序完成时继续执行


如果在所有处理程序完成之前触发事件的代码不需要继续,那么您需要重新构造此类,以便事件处理程序能够在完成时向此类指示。有很多方法可以做到这一点,从在事件中传递一个参数,允许处理程序在完成时告诉它,或者让事件处理程序的签名返回一个
任务
,而不是
无效
(触发事件时需要
等待这些任务)。

请发布,因此,我们可以看到整个画面。请发布a,以便我们可以看到整个画面。请发布a,以便我们可以看到整个画面。请发布a,以便我们可以看到整个画面。请注意,
任务
-返回事件处理程序需要一些工作才能使其正常工作,因为直接调用委托只会从一个订阅者返回一个
任务
。我认为按顺序触发的事件只是当前的实现细节,将来不应该依赖它。斯维克,你能详细说明一下如何为多个订户实现它吗?我觉得返回任务才是解决问题的方法。@ollo您可以使用
GetInvocationList()
。有关更多详细信息,请参阅的第1点中的代码段。请注意,
Task
-返回事件处理程序需要一些工作才能使其正常工作,因为直接调用delega