C# - Return WCF Rest 服务的进度

C# - Return progress from WCF Rest Service

在我的服务中,我目前有一些任务和一个不断更新列表的 ReportProgress 方法。我如何 return 将该列表添加到我的客户端主机应用程序?

服务端:

public async void BeginSync(string dbId)
{
    var progressIndicator = new Progress<string>(ReportSyncProgress);
    var output = await BeginSyncTaskAsync(dbId, progressIndicator);                             
}

...在任务中我有一个循环的进度报告:

while ((output = process.StandardOutput.ReadLine()) != null)
{
    progress.Report(output);        
}

...这是我的举报方式:

public void ReportSyncProgress(string value)
{
    // report by appending to global list
    progressOutput.Add(value);
}

progressOutput 是一个列表,我需要我的客户在更新时实时接收它。

谢谢!

因为 Rest 服务没有会话,所以您无法创建正常的 WCF 回调方法。相反,您需要做的是传入某种令牌,然后使用该令牌获取进度信息。

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