【发布时间】:2015-09-09 23:39:54
【问题描述】:
我正在努力学习 TPL。我以这样的并行方式写入文件:
public async Task SaveToFilesAsync(string path, List<string> list, CancellationToken ct)
{
int count = 0;
foreach (var str in list)
{
string fullPath = path + @"\" + count.ToString() + "_element.txt";
using (var sw = File.CreateText(fullPath))
{
await sw.WriteLineAsync(str);
}
count++;
Log("Saved in thread: {0} to {1}",
Environment.CurrentManagedThreadId,
fullPath);
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
}
}
然后这样称呼它:
var tasks = new List<Task>();
try
{
tasks.Add(SaveToFilesAsync(path, myListOfStrings, cts.Token));
}
catch (Exception ex)
{
Log("Failed to save: " + ex.Message);
throw;
}
tasks.Add(MySecondFuncAsync(), cts.Token);
//...
tasks.Add(MyLastFuncAsync(), cts.Token);
try
{
//Or should I call await Task.WhenAll(tasks) ? What should I call here?
Task.WaitAll(tasks.ToArray());
}
catch (AggregateException ex)
{
foreach (var v in ex.InnerExceptions)
Error(ex.Message + " " + v.Message);
}
finally
{
cts.Dispose();
}
foreach (task in tasks)
{
// Now, how to print results from the tasks?
//Considering that all tasks return bool value,
//I need to do something like this:
if (task.Status != TaskStatus.Faulted)
Console.Writeline(task.Result);
else
Log("Error...");
}
我的目标是让所有功能(SaveToFilesAsync、MySecondFuncAsync)以并行方式同时运行,使用计算机上的所有内核并节省时间。但是当我看到SaveToFilesAsync 的日志时,我意识到保存到文件总是发生在同一个线程中,而不是并行发生。我究竟做错了什么?第二个问题:如何从代码末尾的任务列表中的每个任务中获取 Task.Result?如果第二个函数返回 Task(bool),如何在我的代码中获取 bool 值?此外,由于我是 TPL 的新人,因此非常欢迎所有关于我的代码的 cmets。
【问题讨论】:
-
你应该把你的两个单独的问题放在两个单独的问题中。
-
我在上面的代码中看不到任何并行性,创建新任务不一定会在单独的线程池线程上启动它们。您是否尝试并行化 SaveToFilesAsync 或要运行的任务列表中的代码?您应该查看具有 ParallelOptions 参数的 Parallel.ForEach() 方法之一。 *编辑:我明白了,您希望 SaveFilesAsync 中的并行性
-
您的
Log()调用是多线程可读的吗?或者它本质上是那些其他任务上下文跳转到的单线程操作?
标签: c# .net concurrency async-await task-parallel-library