我需要一次处理N个文件,所以我已经将所有文件信息存储在Dictionary
和Filename, Size, and SequenceNo
中,现在我要从该Dictionary
中选择5个文件,然后处理该文件,与此同时,如果完成对任何文件的处理,则它将从该词典中选择另一个文件。
例如:
如果词典中有10个文件,然后从词典中选择前5个文件File 1, File 2, File 3, File 4, File 5
并进行处理。如果过程File 3
完成,则应该开始File 6
的过程。
所以请帮助我。
谢谢。
答案 0 :(得分:1)
谢谢@netmage,我终于在 ConcurrentBag 的用户那里找到了答案,所以我将发布自己问题的答案。
有一个名称空间提供了System.Collections.Concurrent的几个线程安全的集合类。我已使用该名称空间中的一个 ConcurrentBag
与 List 不同, ConcurrentBag 包允许我们在对其进行迭代时进行修改。它也是线程安全的,并允许并发访问。
我已经实现了以下代码来解决我的问题。
我已声明 ConcurrentBag 对象 FileData 为全局。
ConcurrentBag<string[]> FileData = new ConcurrentBag<string[]>();
创建了一个函数来获取文件信息并将其存储到 FileData 。
private void GetFileInfoIntoBag(string DirectoryPath)
{
var files = Directory.GetFiles(DirectoryPath, " *", SearchOption.AllDirectories);
foreach (var file in files)
{
FileInfo f1 = new FileInfo(file);
fileData = new string[4];
fileData[0] = f1.Name;
fileData[1] = GetFileSize.ToActualFileSize(f1.Length, 2);
fileData[2] = Convert.ToString(i);
fileData[3] = f1.FullName;
i++;
FileData.Add(fileData);
}
}
然后在进行上传过程时,我根据需要创建了 N 任务,并在其中执行了上传逻辑。
private void Upload_Click(object sender, EventArgs e)
{
List<Task> tskCopy = new List<Task>();
for (int i = 0; i < N; i++)
{
tskCopy.Add(Task.Run(() =>
{
while (FileData.Count > 0)
{
string[] file;
FileData.TryTake(out file);
if (file != null && file.Count() > 3)
{
/* Upload Logic*/
GC.Collect();
}
}
}));
}
Task.WaitAll(tskCopy.ToArray());
MessageBox.Show("Upload Complited Successfully");
}
谢谢大家的支持。
答案 1 :(得分:0)
显然,您希望按特定顺序处理文件,一次最多处理五个。
到目前为止,有关文件的信息按顺序存储在List<T>
中。
在列表中移动的一种直接方法是将要访问的下一个元素的索引存储在int
变量中,例如nextFileIndex
。您将其初始化为0
。
开始处理其中一个文件时,请从列表中获取信息:
MyFileInfo currentFile;
lock (myFiles)
{
if (nextFileIndex < myFiles.Count)
{
currentFile = myFiles[nextFileIndex++];
}
}
您一开始就开始了五个“过程”,只要其中一个结束,就开始一个新的过程。
现在,要让这些“进程”并行运行(似乎就是您想要的),请阅读有关多线程的信息,例如.NET的task parallel library。我的建议是创建五个任务,只要nextFileIndex
不超过列表中的最大索引,就抓取下一个文件,并使用类似Task<TResult>.WaitAll
的方法来等待直到所有任务都没有任何东西再做。
请注意多线程问题。