我有类似于以下的API,它接受委托报告操作的进度。同时返回任务以便取消它。
如果此函数的用户对多个函数调用使用相同的委托实例,那么用户如何 确定哪个函数调用的进度。
class Program
{
public static Task LongOperationAsync(List<String> names, Action<String> progress)
{
return Task.Factory.StartNew(() =>
{
foreach (var item in names)
{
// do some long operation
progress(item.ToUpper());
}
});
}
static void Main(string[] args)
{
var friends = new List<String>() {"joey","ross","chandler","monica","phoebe","rachel" };
var seinfelds = new List<String>() { "Jerry", "kramer", "george", "elaine" };
Action<String> resultProcessor = (result) =>
{
// process the result. let's say update the UI as and when results arrive
Console.WriteLine(result);
};
var task1 = LongOperationAsync(friends, resultProcessor);
var task2 = LongOperationAsync(seinfelds, resultProcessor);
Task.WaitAll(task1, task2);
Console.ReadLine();
}
}
答案 0 :(得分:0)
所以我有两个问题
实际上,我看到三个。这是你的第一个(缺少问号不会让它成为问题:)):
用户如何确定哪个函数调用的进度。
您希望用户如何确定?使用您发布的代码,根本不可能。您可以通过多种方式解决此问题,但如果您正在讨论重新使用相同的委托实例,则必须修改调用的方法:
public static Task LongOperationAsync(List<String> names, Action<String> progress, string id)
{
return Task.Factory.StartNew(() =>
{
foreach (var item in names)
{
// do some long operation
progress($"{id}: {item.ToUpper()}");
}
});
}
static void Main(string[] args)
{
var friends = new List<String>() {"joey","ross","chandler","monica","phoebe","rachel" };
var scienfelds = new List<String>() { "Jerry", "kramer", "george", "elaine" };
Action<String> resultProcessor = (result) =>
{
// process the result. let's say update the UI as and when results arrive
Console.WriteLine(result);
};
var task1 = LongOperationAsync(friends, resultProcessor, "task1");
var task2 = LongOperationAsync(scienfelds, resultProcessor, "task2");
Task.WaitAll(task1, task2);
Console.ReadLine();
}
或者相关的替代方案,如果您希望回调本身能够知道进度所针对的任务:
public static Task LongOperationAsync(List<String> names, Action<String, String> progress, string id)
{
return Task.Factory.StartNew(() =>
{
foreach (var item in names)
{
// do some long operation
progress(item.ToUpper(), id);
}
});
}
你的其他问题“主要是基于意见的”,所以不太适合Stack Overflow,但是因为我正在写作,所以这是我的两分钱:
•为获取委托(Action或Func)的函数获取用户提供的信息总是好的做法吗?
始终?不,这取决于具体情况。
•建议在多个函数调用中重用委托实例吗?
这也取决于背景。如果您可以方便地执行此操作,或者如果您处于必须创建大量委托实例的情况下,那么您应该重用一个实例。
但只要没有严重的性能问题(并且通常不存在),您应该以最有意义的方式编写代码,而不是担心创建对象。
例如,代码不重用的代码的替代方法如下所示:
static void Main(string[] args)
{
var friends = new List<String>() {"joey","ross","chandler","monica","phoebe","rachel" };
var scienfelds = new List<String>() { "Jerry", "kramer", "george", "elaine" };
Action<String, String> resultProcessor = (result, id) =>
{
// process the result. let's say update the UI as and when results arrive
Console.WriteLine($"{id}: {result}");
};
var task1 = LongOperationAsync(friends, r => resultProcessor(r, "task1"));
var task2 = LongOperationAsync(scienfelds, r => resultProcessor(r, "task2"));
Task.WaitAll(task1, task2);
Console.ReadLine();
}
通过这种方式,可以根据客户端代码的需要定制回调,而无需更改被调用者(即不需要更改为LongOperationAsync()
)。被呼叫者可以对可能存在的呼叫者类型保持不可知。
是的,您最终必须创建其他委托实例。但那又怎么样?你在这里经营了很长时间。你不会在一秒钟内创建它们甚至十几个,更不用说在性能问题开始成为一个问题之前它需要的成千上万,更别说真的有是解决。