mardi 2 juin 2015

Triggering events from async/await functions in the right order

I have problems ensuring the order of events in my asynchronous task. The class from which other async tasks inherit has the following functions and takes the EventHandlers (ExecutionProgress, ExecutionStarted, ExecutionCompleted) in the constructor arguments:

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)

}

Now in one of my classes, that inherits from asynchronous tasks, i override Operation with the following:

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);
}

Running this code often, but not always, results in NullReference Exception in the ExecutionCompleted event handler when trying to access the JobResults. This is because ExecutionProgress event which writes the member variable usually gets fired after ExecutionCompleted for whatever reason. I think the standard says nothing about event ordering, but I'm looking for a nice solution to ensure deterministic ordering here. I want to fire ExecutionCompleted only after all ExecutionProgress events have been handled.

What would be a nice looking solution here? Is there any way to await until all progress reporting events have been handled.

Aucun commentaire:

Enregistrer un commentaire