In my service I currently have a few tasks and a ReportProgress method that continually updates a List. How can I return that list to my client host application?
Service side:
public async void BeginSync(string dbId)
{
var progressIndicator = new Progress<string>(ReportSyncProgress);
var output = await BeginSyncTaskAsync(dbId, progressIndicator);
}
...within the task I have a progress Report in a loop:
while ((output = process.StandardOutput.ReadLine()) != null)
{
progress.Report(output);
}
...and here is my report method:
public void ReportSyncProgress(string value)
{
// report by appending to global list
progressOutput.Add(value);
}
progressOutput is a List and I need my client to receive that in real time as it is updated.
Thank you!
Because Rest services don't have sessions you can't make normal WCF callback method. Instead what you will need to do is pass in some kind of token and then use that token to get the progress information.
private static ConcurrentDictionary<Guid, ConcurrentQueue<string>> _progressInfo;
//You should never do "async void" WCF can handle using tasks and having Async suffixes.
//see https://blogs.msdn.microsoft.com/endpoint/2010/11/12/simplified-asynchronous-programming-model-in-wcf-with-asyncawait/
public async Task BeginSyncAsync(string dbId, Guid progressKey)
{
if (!_progressInfo.TryAdd(progressKey, new ConcurrentQueue<string>()))
{
throw new InvalidOperationException("progress key is in use");
}
var progressIndicator = new Progress<string>((value) => ReportSyncProgress(value, progressKey));
try
{
var output = await BeginSyncTaskAsync(dbId, progressIndicator);
}
finally
{
//Remove progress list
ConcurrentQueue<string> temp;
_progressInfo.TryRemove(progressKey, out temp);
}
}
public List<string> GetSyncProgress(Guid progressKey)
{
ConcurrentQueue<string> progressOutput;
if (!_progressInfo.TryGetValue(progressKey, out progressOutput))
{
//the key did not exist, retun null;
return null;
}
//transform the queue to a list and return it.
return progressOutput.ToList();
}
private void ReportSyncProgress(string value, Guid progressKey)
{
ConcurrentQueue<string> progressOutput;
if (!_progressInfo.TryGetValue(progressKey, out progressOutput))
{
//the key did not exist, progress is being reported for a completed item... odd.
return;
}
//This is the requests specific queue of output.
progressOutput.Enqueue(value);
}