Описано, конечно сумбурно.
Но похоже на классический producer/consumer.
Это проще на BlockingCollection сделать.
Типа такого:
class Processor<T>
{
private BlockingCollection<Job> jobs = new BlockingCollection<Job>
private class Job {
public readonly T Data;
public readonly Action Callback;
public Job(T data, Action callback = null) { ... }
}
public void AddJob(T data) {
jobs.Add(new Job(data));
}
public void AddJob(T data, Action onCompleted) {
jobs.Add(new Job(data, onCompleted));
}
public void Start(CancellationToken ct = default) {
foreach(var job in jobs.GetConsumingEnumerable(ct)) {
SaveToDb(item.Data);
if (item.Callback !== null) {
Task.Run(() => item.Callback());
}
}
}
public void Stop() {
jobs.CompleteAdding();
}
private void SaveToDb() { ... }
}
// Обычный добавлятель
processor.AddJob(new Data());
// Добавлятель, которому надо подождать
var data = new Data();
processor.AddJob(data, () => {
// Data saved, keep processing
});
Или можно на TaskCompletionSource переписать, т.е. будет что-то типа
Task AddJobAndWait(T data),
под которым лежит TaskCompletionSource и processor после сохранения будет делать tcs.SetResult(true).
Тогда добавлятель сможет ждать или await'ить на таске.