有没有办法合并一些IProgress<float>对象?



我想合并两个IProgress对象合并到一个IProgress<其中T是一个数字。它应该总是返回所有合并进程的平均值。例如progress1>

这可能看起来像这样,但到目前为止,我还没有找到一种方法来合并两个或多个IProgress对象:

IProgress<float> p1 = new Progress(value=> Console.WriteLine(value));
IProgress<float> p2 = new Progress(value=> Console.WriteLine(value));
IProgress<float> pM = Progress.Merge(p1,p2,value=> Console.WriteLine("Full progress: " + value));
到目前为止,我只找到了一种方法,当创建Progress对象以在另一个Progress中输出通道时,我必须这样做。我将返回值存储在一个数组中,然后手动计算平均值,因为方法" average ()"不能工作,因为多个线程将访问数组:
float[] progress = new float[2]
IProgress<float> pM = new Progress(value=>
{  
double p=0;
for (int i = 0; i < progress.Length; i++)
{
p+=progress[i]
}
Console.WriteLine("Full progress: " + p/progress.Length)
});
IProgress<float> p1 = new Progress(value=>{ progress[0]=value; pM.Report(0); });
IProgress<float> p2 = new Progress(value=>{ progress[1]=value; pM.Report(0); });

是否有办法合并Progress对象?

您可以编写自己的合并器:

public sealed class ProgressAmalgamator : Progress<double>
{
public void Attach(Progress<double> progress)
{
lock (_lock)
{
_progressors.Add(progress);
_progress.Add(0);
progress.ProgressChanged += progress_ProgressChanged;
}
}
void progress_ProgressChanged(object? sender, double e)
{
double average = 0;
lock (_lock)
{
for (int i = 0; i < _progressors.Count; i++)
{
if (ReferenceEquals(_progressors[i], sender))
{
_progress[i] = e;
break;
}
}
average = _progress.Average();
}
OnReport(average);
}
readonly List<IProgress<double>> _progressors = new();
readonly List<double> _progress = new();
readonly object _lock = new object();
}

这假设所有的进度源都使用相同的缩放-如果他们不这样做,计算的平均值当然是不正确的。

使用它的示例控制台应用程序(注意Console.WriteLine()progress_ProgressChanged()的添加,您不希望在生产代码中):

namespace Console1;
public static class Program
{
public static async Task Main()
{
var progress1 = new Progress<double>();
var progress2 = new Progress<double>();
var progress3 = new Progress<double>();
var amalgamator = new ProgressAmalgamator();
amalgamator.Attach(progress1);
amalgamator.Attach(progress2);
amalgamator.Attach(progress3);
amalgamator.ProgressChanged += (_, progress) => Console.WriteLine($"Amalgamated progress = {progress}");
Task[] tasks =
{
Task.Run(() => simulateProgress("A", progress1, 10, 1000)),
Task.Run(() => simulateProgress("B", progress2, 20, 2000)),
Task.Run(() => simulateProgress("C", progress3, 50, 5000))
};
await Task.WhenAll(tasks);
Console.WriteLine("All tasks completed.");
Console.ReadLine();
}
static void simulateProgress(string name, IProgress<double> progress, double step, int delay)
{
double current = 0;
while (current < 100)
{
Thread.Sleep(delay);
current += step;
Console.WriteLine($"Thread {name} is reporting progress = {current}");
progress.Report(Math.Min(current, 100));
}
}
}
public sealed class ProgressAmalgamator : Progress<double>
{
public void Attach(Progress<double> progress)
{
lock (_lock)
{
_progressors.Add(progress);
_progress.Add(0);
progress.ProgressChanged += progress_ProgressChanged;
}
}
void progress_ProgressChanged(object? sender, double e)
{
double average = 0;
lock (_lock)
{
for (int i = 0; i < _progressors.Count; i++)
{
if (ReferenceEquals(_progressors[i], sender))
{
Console.WriteLine($"Setting progress for progressor {i} to {e}");
_progress[i] = e;
break;
}
}
average = _progress.Average();
}
OnReport(average);
}
readonly List<IProgress<double>> _progressors = new();
readonly List<double> _progress = new();
readonly object _lock = new object();
}

样本输出:

Thread A is reporting progress = 10
Setting progress for progressor 0 to 10
Amalgamated progress = 3.3333333333333335
Thread A is reporting progress = 20
Thread B is reporting progress = 20
Setting progress for progressor 0 to 20
Setting progress for progressor 1 to 20
Amalgamated progress = 6.666666666666667
Amalgamated progress = 13.333333333333334
Thread A is reporting progress = 30
Setting progress for progressor 0 to 30
Amalgamated progress = 16.666666666666668
Thread A is reporting progress = 40
Thread B is reporting progress = 40
Setting progress for progressor 0 to 40
Amalgamated progress = 20
Setting progress for progressor 1 to 40
Amalgamated progress = 26.666666666666668
Thread C is reporting progress = 50
Setting progress for progressor 2 to 50
Amalgamated progress = 43.333333333333336
Thread A is reporting progress = 50
Setting progress for progressor 0 to 50
Amalgamated progress = 46.666666666666664
Thread B is reporting progress = 60
Setting progress for progressor 1 to 60
Amalgamated progress = 53.333333333333336
Thread A is reporting progress = 60
Setting progress for progressor 0 to 60
Amalgamated progress = 56.666666666666664
Thread A is reporting progress = 70
Setting progress for progressor 0 to 70
Amalgamated progress = 60
Thread B is reporting progress = 80
Setting progress for progressor 1 to 80
Amalgamated progress = 66.66666666666667
Thread A is reporting progress = 80
Setting progress for progressor 0 to 80
Amalgamated progress = 70
Thread A is reporting progress = 90
Setting progress for progressor 0 to 90
Amalgamated progress = 73.33333333333333
Thread C is reporting progress = 100
Setting progress for progressor 2 to 100
Amalgamated progress = 90
Thread B is reporting progress = 100
Setting progress for progressor 1 to 100
Amalgamated progress = 96.66666666666667
Thread A is reporting progress = 100
Setting progress for progressor 0 to 100
Amalgamated progress = 100
All tasks completed.

相关内容

最新更新