gpt4 book ai didi

c# - 跟踪多步骤任务的进度

转载 作者:太空狗 更新时间:2023-10-30 01:11:05 24 4
gpt4 key购买 nike

我正在开发一个向客户端公开网络服务的简单服务器。有些请求可能需要很长时间才能完成,并且在逻辑上分为多个步骤。对于此类请求,需要在执行过程中报告进度。此外,新的请求可能会在前一个请求完成之前启动,并且要求两者同时执行(除非有一些系统特定的限制)。

我正在考虑让服务器向其客户端返回一个 TaskId,并让客户端使用 TaskId 跟踪请求的进度。我认为这是一个很好的方法,我剩下的问题是如何管理任务。

从未使用过 TPL,我认为这是解决此问题的好方法。事实上,它允许我同时运行多个任务,而无需手动管理线程。我什至可以使用 ContinueWith 相对轻松地创建多步骤任务。

不过,我想不出一个跟踪任务进度的好方法。我意识到当我的请求包含单个“步骤”时,该步骤必须合作报告其状态。这是我现在希望避免的事情。但是,当请求包含多个步骤时,我想知道当前正在执行哪个步骤并相应地报告进度。我能想出的唯一方法非常烦人:

Task<int> firstTask = new Task( () => { DoFirstStep(); return 3.14; } );
firstTask.
ContinueWith<int>( task => { UpdateProgress("50%"); return task.Result; } ).
ContinueWith<string>( task => { DoSecondStep(task.Result); return "blah"; }.
ContinueWith<string>( task => { UpdateProgress("100%"); return task.Result; } ).

甚至这也不完美,因为我希望任务存储自己的进度,而不是让 UpdateProgress 更新某个已知位置。此外,它还有一个明显的缺点,即在添加新步骤时必须更改很多地方(从现在开始,进度为 33%、66%、100%,而不是 50%、100%)。

谁有好的解决方案?

谢谢!

最佳答案

这并不是任务并行库完全支持的场景。

您可能会考虑将进度更新提供给队列并在另一个任务中读取它们的方法:

static void Main(string[] args)
{
Example();
}

static BlockingCollection<Tuple<int, int, string>> _progressMessages =
new BlockingCollection<Tuple<int, int, string>>();

public static void Example()
{
List<Task<int>> tasks = new List<Task<int>>();

for (int i = 0; i < 10; i++)
tasks.Add(Task.Factory.StartNew((object state) =>
{
int id = (int)state;
DoFirstStep(id);
_progressMessages.Add(new Tuple<int, int, string>(
id, 1, "10.0%"));
DoSecondStep(id);
_progressMessages.Add(new Tuple<int, int, string>(
id, 2, "50.0%"));

// ...

return 1;
},
(object)i
));

Task logger = Task.Factory.StartNew(() =>
{
foreach (var m in _progressMessages.GetConsumingEnumerable())
Console.WriteLine("Task {0}: Step {1}, progress {2}.",
m.Item1, m.Item2, m.Item3);
});


List<Task> waitOn = new List<Task>(tasks.ToArray());
waitOn.Add(logger);
Task.WaitAll(waitOn.ToArray());
Console.ReadLine();
}

private static void DoSecondStep(int id)
{
Console.WriteLine("{0}: First step", id);
}

private static void DoFirstStep(int id)
{
Console.WriteLine("{0}: Second step", id);
}

此示例不显示取消、错误处理或考虑您的任务可能长时间运行的要求。长时间运行的任务对调度程序提出了特殊要求。关于此的更多讨论可以在 http://parallelpatterns.codeplex.com/ 找到。 , 下载本书草稿并查看第 3 章。

这只是在这种情况下使用任务并行库的一种方法。 TPL 很可能不是这里的最佳方法。

如果您的 Web 服务在 ASP.NET(或类似的 Web 应用程序服务器)中运行,那么您还应该考虑使用线程池中的线程执行任务而不是服务 Web 请求可能产生的影响:

How does Task Parallel Library scale on a terminal server or in a web application?

关于c# - 跟踪多步骤任务的进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3395379/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com